编写我的fmap时遇到问题

Jon*_*off 2 haskell functor

我正在尝试为这种类型编写一个fmap

data Triangle a  = Triangle {t0 :: Point a, t1 ::  Point a, t2 ::  Point a}
Run Code Online (Sandbox Code Playgroud)

其中Point定义为

data Point a = Point {px :: a, py :: a, pz :: a}
Run Code Online (Sandbox Code Playgroud)

而我的实例def是

instance Functor Triangle where 
    fmap f (Triangle v0 v1 v2) = Triangle (f v0) (f v1) (f v2)
Run Code Online (Sandbox Code Playgroud)

我收到以下恭维错误,我无法弄清楚为什么

 C:\Scripts\Haskell\Geometry.hs:88:1:
     Occurs check: cannot construct the infinite type: a = Point a
     When generalising the type(s) for `fmap'
     In the instance declaration for `Functor Triangle'

有任何想法吗?

sdc*_*vvc 8

instance Functor Point where
    fmap f (Point v0 v1 v2) = Point (f v0) (f v1) (f v2)

instance Functor Triangle where
    fmap f (Triangle v0 v1 v2) = Triangle (fmap f v0) (fmap f v1) (fmap f v2)
Run Code Online (Sandbox Code Playgroud)

在Triangle实例中,fa -> b.我们必须把它转换成Point a -> Point b第一个.然后我们可以fmap f转换Triangle aTriangle b.(观察你正在申请f9件物品,如果我理解你的意图正确的话)[编辑:是27]


Chr*_*way 8

前面的答案为您提供了正确的解决方案,但更明确地了解这里发生的事情可能会有所帮助.类型fmap

fmap :: Functor f => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

因此,您的instance声明的类型推断过程如下:

  1. fmap f (Triangle v0 v1 v2),f必须有一些类型a -> b,(Triangle v0 v1 v2)必须有类型Triangle a.
    • 通过定义Triangle,v0,v1,并且v2必须有类型Point a.
    • 由于f被施加到v0,v1以及v2,它的参数类型a必须是Point a.
    • 糟糕,a = Point a不可满足.

为什么定义Triangle (fmap f v0) (fmap f v1) (fmap f v2)有效?:

  1. fmap f (Triangle v0 v1 v2),f必须有一些类型a -> b,(Triangle v0 v1 v2)必须有类型Triangle a.
    • 通过定义Triangle,v0,v1,并且v2必须有类型Point a.
    • 假设Point是一个实例Functor,如上所述,fmap f v0必须具有类型Point b,其中b是结果类型f.同样的v1v2.
    • 因此Triangle (fmap f v0) (fmap f v1) (fmap f v2)有类型Triangle b.
    • QED.