模式中的解析错误:f。克
我是初学者,哪里错了?
(f . g) x = f (g x)
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor g where
fmap :: (a -> b) -> f a -> f b
instance Functor F where
fmap id = id
fmap (f . g) = fmap f . fmap g
答案 0 :(得分:9)
当您创建Functor的实例时,您应证明
的边条件fmap id = id
和
fmap (f . g) = fmap f . fmap g
(从技术上讲,后者是免费的,因为涉及的类型和前法律,但它仍然是一个很好的练习。)
你不能仅仅通过说
来做到这一点fmap id = id
但是你用它作为推理工具 - 一旦你证明了它。
尽管如此,由于种种原因,您编写的代码没有意义。
(f . g) x = f (g x)
由于这是缩进的,我有点不清楚这是否是(。)的定义,但是已经包含在Prelude中,所以你不需要再次定义它。
class Functor f where
fmap :: (a -> b) -> f a -> f b
Prelude中也提供了这个定义。
class Functor g where
fmap :: (a -> b) -> f a -> f b
但是你再次定义了这个类,但是在这里它已经破坏了fmap的签名,这必须是
fmap :: (a -> b) -> g a -> g b
但是正如你上面有另一个Functor的定义(并且Prelude还有另一个,你无法编译)
最后,你的
instance Functor F where
fmap id = id
fmap (f . g) = fmap f . fmap g
为您要在F
的实例中创建的类型组成名称Functor
,然后尝试将法律作为实现,而不是它的工作方式。< / p>
让我们举一个如何运作的例子。
考虑一个非常简单的仿函数:
data Pair a = Pair a a
instance Functor Pair where
fmap f (Pair a b) = Pair (f a) (f b)
现在,为了证明fmap id = id
,让我们考虑一下fmap id
和id
做点:
fmap id (Pair a b) = -- by definition
Pair (id a) (id b) = -- by beta reduction
Pair a (id b) = -- by beta reduction
Pair a b
id (Pair a b) = -- by definition
Pair a b
所以,在这种特殊情况下fmap id = id
。
然后你可以检查(虽然技术上给出了上述内容,但你没有)fmap f . fmap g = fmap (f . g)
(fmap f . fmap g) (Pair a b) = -- definition of (.)
fmap f (fmap g (Pair a b)) = -- definition of fmap
fmap f (Pair (g a) (g b)) = -- definition of fmap
Pair (f (g a)) (f (g b))
fmap (f . g) (Pair a b) = -- definition of fmap
Pair ((f . g) a) ((f . g) b) = -- definition of (.)
Pair (f (g a)) ((f . g) b) = -- definition of (.)
Pair (f (g a)) (f (g b))
所以fmap f . fmap g = fmap (f . g)
现在,您可以将函数组合转换为仿函数。
class Functor f where
fmap :: (a -> b) -> f a -> f b
部分应用函数箭头构造函数。
请注意,a -> b
和(->) a b
的含义相同,所以当我们说
instance Functor ((->) e) where
fmap的签名专门用于
fmap {- for (->) e -} :: (a -> b) -> (->) e a -> (->) e b
一旦你翻过箭头看起来像
fmap {- for (->) e -} :: (a -> b) -> (e -> a) -> e -> b
但这只是功能组合的签名!
所以
instance Functor ((->)e) where
fmap f g x = f (g x)
是一个非常合理的定义,甚至是
instance Functor ((->)e) where
fmap = (.)
它实际上显示在Control.Monad.Instances。
所以你需要使用它
import Control.Monad.Instances
并且您根本不需要编写任何代码来支持这一点,您可以使用fmap
作为特殊情况的函数组合,例如
fmap (+1) (*2) 3 =
((+1) . (*2)) 3 =
((+1) ((*2) 3)) =
((+1) (3 * 2)) =
3 * 2 + 1 =
7
答案 1 :(得分:2)
由于.
不是数据构造函数,因此我不能将它用于模式匹配。据我所知,没有一种简单的方法可以做你正在尝试的事情,尽管我对Haskell也很陌生。
答案 2 :(得分:2)
let
不用于顶级绑定,只需执行:
f . g = \x -> f (g x)
但是,正如cobbal所说的那样,抱怨约为fmap (f . g)
,这是无效的。实际上,整个class Functor F where
是棘手的。该类已经声明,现在我想你要制作和instance
:
instance Functor F where
fmap SomeConstructorForF = ...
fmap OtherConstructorForF = ...
等