方阵函数
Functor for square matrices
在我之前的问题 () 中,引入了数据类型 Square
。现在我想为它写一个仿函数实例。所以我从所有四种类型的地图函数开始。我已经为 Nil
和 Cons
:
做到了
mapNil :: ((a -> b) -> a -> b) -> (Nil (a -> b) -> Nil a -> Nil b )
mapNil map f Nil = Nil
mapCons :: (forall b . ((a -> b) -> a -> b) -> (t (a -> b) -> t a -> t b))
-> ((a -> b) -> a -> b)
-> ((Cons t (a -> b)) -> Cons t a -> Cons t b)
mapCons mapT mapA (Cons f consf) (Cons x consx) = Cons (mapA f x) (mapT mapA consf consx)
现在,Square'
类型:
mapSquare' :: (forall b . ((a -> b) -> a -> b) -> (t (a -> b) -> t a -> t b))
-> ((a -> b) -> a -> b)
-> ((Square' t (a -> b)) -> Square' t a -> Square' t b)
mapSquare' mapT mapA (Zero fs) (Zero xs) = Zero (mapT (mapT mapA) fs xs) -- it is wrong
mapSquare' mapT mapA (Succ fs) (Succ xs) = mapSquare' (mapCons mapT) mapA fs xs
然后我会做这样的事情:
mapSquare = ...
-- this is, actually, the final goal:
instance Functor Square where
fmap = mapSquare
到目前为止,我的 mapSquare'
Haskell 是这样说的:
• Occurs check: cannot construct the infinite type: a ~ t a
Expected type: (a -> t b) -> a -> t b
Actual type: t (a -> b) -> t a -> t b
• In the first argument of ‘mapT’, namely ‘(mapT mapA)’
In the first argument of ‘Zero’, namely ‘(mapT (mapT mapA) fs xs)’
In the expression: Zero (mapT (mapT mapA) fs xs)
我的计划是 (mapT mapA)
将 "lift" 全部介于 (t (t a))
和 (t a)
之间。我的错误是什么?我将不胜感激你的帮助。
您不能使用 mapSquare
,因为该类型限制太多。函子的类型为 fmap :: Functor f => (c -> d) -> f c -> f d
。但是 ((a -> b) -> a -> b) -> (Square (a -> b)) -> Square a -> Square b
只会涵盖其中的一个子集。您的 mapSquare'
看起来更像是“ 顺序应用程序 ” (<*>) :: Applicative f => f (a -> b) -> f a -> f b
。请注意 (<*>)
需要两个 f <i>x</i>
项,而不是一个,就像 fmap
那样。
如果你想声明 Square
Functor
的一个实例,根据你的实现方式,Nil
和 Const
可能需要也是 Functor
的一个实例。我们可以很容易地使这些成为 Functor
:
的实例
instance Functor Nil where
fmap _ Nil = Nil
instance Functor t => Functor (Cons t) where
fmap f (Cons x xs) = Cons (f x) (fmap f xs)
现在我们可以使 Square'
成为 Functor
的一个实例:
instance Functor t => Functor (Square' t) where
fmap f (Zero x) = Zero (fmap (fmap f) x)
fmap f (Succ x) = Succ (fmap f x)
你实际上并没有自己生成那些。您可以使用 DeriveFunctor
[ghc-doc] 编译器选项,让编译器为您派生函数:
{-# LANGUAGE <b>DeriveFunctor</b> #-}
data Square' t a = Zero (t (t a) ) | Succ (Square' (Cons t) a) <b>deriving Functor</b>
data Nil a = Nil <b>deriving Functor</b>
data Cons t a = Cons a (t a) <b>deriving Functor</b>
这将构造此处讨论的指定函子。
这里是我想问的问题的答案,而不是实际问的,因为我的表达方式有点含糊。
首先,我确实搞砸了 (<*>)
和 fmap
,感谢@WillemVanOnsem 指出了这一点。
所以,我真正想做的是:
mapNil :: ((a -> b) -> a -> b) -> ((a -> b) -> Nil a -> Nil b )
mapNil mapA f Nil = Nil
mapCons :: (forall b . ((a -> b) -> a -> b) -> ((a -> b) -> t a -> t b))
-> ((a -> b) -> a -> b)
-> ((a -> b) -> Cons t a -> Cons t b)
mapCons mapT mapA f (Cons x consx) = Cons (f x) (mapT mapA f consx)
然后...
mapSquare' :: (forall b . ((a -> b) -> a -> b) -> ((a -> b) -> t a -> t b))
-> ((a -> b) -> a -> b)
-> ((a -> b) -> Square' t a -> Square' t b)
mapSquare' mapT mapA f (Zero xs) = Zero (mapT (mapT mapA) f xs)
mapSquare' mapT mapA f (Succ xs) = Succ (mapSquare' (mapCons mapT) mapA f xs)
t
是类型 * -> *
的类型构造函数,因此 t
(mapT
) 上的映射函数应该在其参数 (mapA
) 作为参数。所以我需要 mapT
和 mapA
在我之前的问题 (Square
。现在我想为它写一个仿函数实例。所以我从所有四种类型的地图函数开始。我已经为 Nil
和 Cons
:
mapNil :: ((a -> b) -> a -> b) -> (Nil (a -> b) -> Nil a -> Nil b )
mapNil map f Nil = Nil
mapCons :: (forall b . ((a -> b) -> a -> b) -> (t (a -> b) -> t a -> t b))
-> ((a -> b) -> a -> b)
-> ((Cons t (a -> b)) -> Cons t a -> Cons t b)
mapCons mapT mapA (Cons f consf) (Cons x consx) = Cons (mapA f x) (mapT mapA consf consx)
现在,Square'
类型:
mapSquare' :: (forall b . ((a -> b) -> a -> b) -> (t (a -> b) -> t a -> t b))
-> ((a -> b) -> a -> b)
-> ((Square' t (a -> b)) -> Square' t a -> Square' t b)
mapSquare' mapT mapA (Zero fs) (Zero xs) = Zero (mapT (mapT mapA) fs xs) -- it is wrong
mapSquare' mapT mapA (Succ fs) (Succ xs) = mapSquare' (mapCons mapT) mapA fs xs
然后我会做这样的事情:
mapSquare = ...
-- this is, actually, the final goal:
instance Functor Square where
fmap = mapSquare
到目前为止,我的 mapSquare'
Haskell 是这样说的:
• Occurs check: cannot construct the infinite type: a ~ t a
Expected type: (a -> t b) -> a -> t b
Actual type: t (a -> b) -> t a -> t b
• In the first argument of ‘mapT’, namely ‘(mapT mapA)’
In the first argument of ‘Zero’, namely ‘(mapT (mapT mapA) fs xs)’
In the expression: Zero (mapT (mapT mapA) fs xs)
我的计划是 (mapT mapA)
将 "lift" 全部介于 (t (t a))
和 (t a)
之间。我的错误是什么?我将不胜感激你的帮助。
您不能使用 mapSquare
,因为该类型限制太多。函子的类型为 fmap :: Functor f => (c -> d) -> f c -> f d
。但是 ((a -> b) -> a -> b) -> (Square (a -> b)) -> Square a -> Square b
只会涵盖其中的一个子集。您的 mapSquare'
看起来更像是“ 顺序应用程序 ” (<*>) :: Applicative f => f (a -> b) -> f a -> f b
。请注意 (<*>)
需要两个 f <i>x</i>
项,而不是一个,就像 fmap
那样。
如果你想声明 Square
Functor
的一个实例,根据你的实现方式,Nil
和 Const
可能需要也是 Functor
的一个实例。我们可以很容易地使这些成为 Functor
:
instance Functor Nil where
fmap _ Nil = Nil
instance Functor t => Functor (Cons t) where
fmap f (Cons x xs) = Cons (f x) (fmap f xs)
现在我们可以使 Square'
成为 Functor
的一个实例:
instance Functor t => Functor (Square' t) where
fmap f (Zero x) = Zero (fmap (fmap f) x)
fmap f (Succ x) = Succ (fmap f x)
你实际上并没有自己生成那些。您可以使用 DeriveFunctor
[ghc-doc] 编译器选项,让编译器为您派生函数:
{-# LANGUAGE <b>DeriveFunctor</b> #-}
data Square' t a = Zero (t (t a) ) | Succ (Square' (Cons t) a) <b>deriving Functor</b>
data Nil a = Nil <b>deriving Functor</b>
data Cons t a = Cons a (t a) <b>deriving Functor</b>
这将构造此处讨论的指定函子。
这里是我想问的问题的答案,而不是实际问的,因为我的表达方式有点含糊。
首先,我确实搞砸了 (<*>)
和 fmap
,感谢@WillemVanOnsem 指出了这一点。
所以,我真正想做的是:
mapNil :: ((a -> b) -> a -> b) -> ((a -> b) -> Nil a -> Nil b )
mapNil mapA f Nil = Nil
mapCons :: (forall b . ((a -> b) -> a -> b) -> ((a -> b) -> t a -> t b))
-> ((a -> b) -> a -> b)
-> ((a -> b) -> Cons t a -> Cons t b)
mapCons mapT mapA f (Cons x consx) = Cons (f x) (mapT mapA f consx)
然后...
mapSquare' :: (forall b . ((a -> b) -> a -> b) -> ((a -> b) -> t a -> t b))
-> ((a -> b) -> a -> b)
-> ((a -> b) -> Square' t a -> Square' t b)
mapSquare' mapT mapA f (Zero xs) = Zero (mapT (mapT mapA) f xs)
mapSquare' mapT mapA f (Succ xs) = Succ (mapSquare' (mapCons mapT) mapA f xs)
t
是类型 * -> *
的类型构造函数,因此 t
(mapT
) 上的映射函数应该在其参数 (mapA
) 作为参数。所以我需要 mapT
和 mapA