haskell - 如何在 Haskell 中使元组成为此类的实例?

标签 haskell types typeclass type-kinds

我一直在阅读“What I wish I knew when learning Haskell”这本书,我在这个例子上停了下来:

class Bifunctor p where
    bimap  :: (a -> b) -> (c -> d) -> p a c -> p b d
    first  :: (a -> b) -> p a c -> p b c
    second :: (b -> c) -> p a b -> p a c

我的问题是:如何创建该类的实例?这个想法是将函数称为:
λ bimap  (+1) (+2) (8, 9) -- (9, 11)
λ first  (*4) (10, 8) -- (40, 8)
λ second (*2) (3, 5) -- (3, 10)

我最接近做到这一点的是:
instance Bifunctor (x, y) where
    bimap func func' (x, y) = (func x, func' y)
    first func (x, y) = (func x, y)
    second func (x, y) = (x, func y)

但它不起作用,它会引发错误:
• Expecting two fewer arguments to ‘(x, y)’
  Expected kind ‘* -> * -> *’, but ‘(x, y)’ has kind ‘*’
• In the first argument of ‘Bifunctor’, namely ‘(x, y)’
  In the instance declaration for ‘Bifunctor (x, y)’

最佳答案

好问题。

该类适用于仿函数类型本身,在您的情况下,仿函数类型是 (,)。要了解它,请注意这里的区别。

:t (,)
(,) :: a -> b -> (a, b)

:t (True,False)
(True,False) :: (Bool, Bool)

如果您使用 Pair 类型,可能会更直观:
data Pair a b = Pair a b

因为阅读类定义会使'p'的类型应用更加明显。

就像 Haskell 使用类型作为值一样,如上所示,它使用类型作为类型(也用于编译时逻辑),这些类型被命名为 Kinds。
:k Pair
Pair :: * -> * -> *

:k (,)
(,) :: * -> * -> *

:k (Bool,Bool)
(Bool,Bool) :: *

:k Bifunctor 
Bifunctor :: (* -> * -> *) -> Constraint


最后一行说明 Bifunctor 类是为类型 (* -> * -> *) 设计的。 , 不友善 (*) (a,b),因此您从 GHC 收到的错误消息。

您的定义几乎是正确的,这是正确的:
instance Bifunctor (,) where
  bimap func func' (x, y) = (func x, func' y)
  first func (x, y) = (func x, y)
  second func (x, y) = (x, func y)

编辑:@leftroundabout 建议的种类说明

关于haskell - 如何在 Haskell 中使元组成为此类的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62258311/

相关文章:

Haskell - 从文件中读取图形规范

haskell - 斐波那契函数正确性的归纳证明

haskell - 将模式匹配限制为构造函数的子集

haskell - 有什么方法可以自定义 GeneralizedNewtypeDeriving 实例的一种或两种方法?

haskell - Cabal Mac OS(雪豹)出错 - ld : unknown option: -no_pie

haskell - 为什么 GHCi 不允许此版本的连接使用类型参数?

Java(隐式类型转换): Does a unary operator affect the data type of the variables in operation?

design-patterns - 设计模式 : What is a type

haskell - 类型族内的多态函数

haskell - 什么时候需要类型注释?