我一直在读书“ 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获得的错误消息。
您的定义几乎正确,这是正确的:
的插图,如@leftroundabout]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)
编辑:种类
(x,y)
已经是一个具体的元组类型,包含两个具体的(尽管未知)类型x
和y
。同时,函子或bifunctor应该是parametric