模式中的解析错误:f。 g在fmap中(f.g)= fmap f。 fmap g

时间:2011-04-02 07:31:28

标签: haskell

模式中的解析错误: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

3 个答案:

答案 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 idid做点:

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 = ...