Haskell 模式f中的分析错误。fmap中的g(f.g)=fmap f。fmap g

Haskell 模式f中的分析错误。fmap中的g(f.g)=fmap f。fmap g,haskell,Haskell,模式f中的分析错误。g 我是初学者,哪里不对 (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) = fm

模式f中的分析错误。g

我是初学者,哪里不对

   (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

因为
不是一个数据构造函数,所以我认为不能将它用于模式匹配。据我所知,没有一种简单的方法可以完成您正在尝试的任务,尽管我对Haskell也很陌生。

不用于顶级绑定,只需执行以下操作:

f . g = \x -> f (g x)
但正如科巴尔所说,投诉是关于fmap(f.g),这是无效的。实际上,整个
类函子F,其中
是螺旋的。该类已经声明,现在我想您需要创建和
实例

instance Functor F where
    fmap SomeConstructorForF = ...
    fmap OtherConstructorForF = ...

等等。

当你做一个函子的实例时,你应该证明

fmap id = id 

(从技术上讲,考虑到涉及的类型和前者的法律,后者是免费的,但这仍然是一个很好的做法。)

你不能只是说

fmap id = id
但是,一旦你证明了这一点,你就可以把它作为一种推理工具

也就是说,由于许多原因,您编写的代码没有意义

  (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 
但是,您再次定义了这个类,但是在这里它破坏了fmap的签名,这必须是

    fmap :: (a -> b) -> g a -> g b
但由于上面有函子的另一个定义(前奏曲还有另一个定义,所以无法编译)

最后,你的

instance Functor F where
    fmap id = id 
    fmap (f . g)  = fmap f . fmap g
为要生成为
Functor
实例的类型生成一个名称
F
,然后尝试将规则作为一个实现,这不是它的工作方式

让我们举一个它应该如何工作的例子

考虑一个非常简单的函子:

data Pair a = Pair a a

instance Functor Pair where
   fmap f (Pair a b) = Pair (f a) (f b)

现在,为了证明<代码> FMAPID= 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)

所以
fmapf。fmap g=fmap(f.g)

现在,你可以把函数合成成一个函子

class Functor f where
    fmap :: (a -> b) -> f a -> f b
通过部分应用函数arrow构造函数

注意,
a->b
(>)ab
的意思是一样的,所以当我们说

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 = (.)
事实上,它出现在

所以你只需要使用它

import Control.Monad.Instances
您根本不需要编写任何代码来支持这一点,您可以使用
fmap
作为函数组合作为特例,例如

fmap (+1) (*2) 3 = 
((+1) . (*2)) 3 =
((+1) ((*2) 3)) =
((+1) (3 * 2)) = 
3 * 2 + 1 =
7

@超级G:我认为你做不到。如何添加一个函数组合来生成f。g工作?如上所述,这是我想做的一个例子。@Super您似乎看到的是类似于这些定律的东西,它们更多的是文档而不是代码,说明函子应该以某种方式运行。如果没有let,输入“=”,将出现:1:8:parse error。@Super G:您不能在GHCi中定义类或实例。您将得到您所看到的语法错误。您需要在文件中定义它们,然后:在GHCi中加载该文件。当然,您会在代码中遇到各种其他错误,但这是您的根本问题。但是,模式f中的解析错误。g、 它似乎不使用该行来进行函数合成谢谢。再次编辑我的问题。我真的希望这样做。因为我还有其他的定义要尝试。
instance Functor ((->)e) where
    fmap = (.)
import Control.Monad.Instances
fmap (+1) (*2) 3 = 
((+1) . (*2)) 3 =
((+1) ((*2) 3)) =
((+1) (3 * 2)) = 
3 * 2 + 1 =
7