编写 fmap 时遇到问题
我正在尝试为此类型编写一个 fmap
data Triangle a = Triangle {t0 :: Point a, t1 :: Point a, t2 :: Point a}
,其中 Point 定义为
data Point a = Point {px :: a, py :: a, pz :: a}
我的实例 def 是
instance Functor Triangle where
fmap f (Triangle v0 v1 v2) = Triangle (f v0) (f v1) (f v2)
我收到以下编译错误,我无法弄清楚为什么
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'
有任何想法吗?
I am trying to write an fmap for this type
data Triangle a = Triangle {t0 :: Point a, t1 :: Point a, t2 :: Point a}
where Point is defined as
data Point a = Point {px :: a, py :: a, pz :: a}
And my instance def is
instance Functor Triangle where
fmap f (Triangle v0 v1 v2) = Triangle (f v0) (f v1) (f v2)
I am getting the following compliation error and I can't figure out why
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'
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
前面的答案为您提供了正确的解决方案,但更明确地了解这里发生的情况可能会有所帮助。
fmap
的类型为因此,
instance
声明的类型推断按如下方式进行:fmap f (Triangle v0 v1 v2)
中,f
必须具有某种类型a -> b
和(Triangle v0 v1 v2)
必须具有类型Triangle a
。Triangle
的定义,v0
、v1
和v2
必须具有类型Point一个
。f
应用于v0
、v1
和v2
,因此其参数类型a
必须是Point a
。a = a 点
无法满足。为什么定义
三角形 (fmap f v0) (fmap f v1) (fmap f v2)
有效? :fmap f (Triangle v0 v1 v2)
中,f
必须具有某种类型a ->; b
和(Triangle v0 v1 v2)
必须具有类型Triangle a
。Triangle
的定义,v0
、v1
和v2
必须具有类型Point一个
。Point
是Functor
的实例,如上所述,fmap f v0
必须具有类型Point b
,其中b
是f
的结果类型。v1
和v2
也是如此。Triangle (fmap f v0) (fmap f v1) (fmap f v2)
的类型为Triangle b
。The previous answer gives you a correct solution, but it might be helpful to be more explicit about what's going on here. The type of
fmap
isSo the type inference for your
instance
declaration proceeds as follows:fmap f (Triangle v0 v1 v2)
,f
must have some typea -> b
and(Triangle v0 v1 v2)
must have typeTriangle a
.Triangle
,v0
,v1
, andv2
must have typePoint a
.f
is applied tov0
,v1
, andv2
, its argument typea
must bePoint a
.a = Point a
is unsatisfiable.Why does the definition
Triangle (fmap f v0) (fmap f v1) (fmap f v2)
work? :fmap f (Triangle v0 v1 v2)
,f
must have some typea -> b
and(Triangle v0 v1 v2)
must have typeTriangle a
.Triangle
,v0
,v1
, andv2
must have typePoint a
.Point
is an instance ofFunctor
, as above,fmap f v0
must have typePoint b
, whereb
is the result type off
. Likewise forv1
andv2
.Triangle (fmap f v0) (fmap f v1) (fmap f v2)
has typeTriangle b
.顺便说一句,Functor 的一个有趣的属性是,只有一个可能的实例可以满足 函子定律。
更好的是,可以使用 derive 包:
恕我直言,这部分是一个胜利,因为如果您决定更改
Triangle
的定义,它的Functor
实例会自动为您维护。Btw, an interesting property of
Functor
is that there is only one possible instance to make that will satisfy the Functor laws.Better yet, this instance can be automatically produced for you using the derive package:
Imho this is a win partially because if you decide to change the definition of
Triangle
, itsFunctor
instance is maintained automatically for you.在 Triangle 实例中,
f
是a -> b.
。我们必须将其转换为 Point a ->首先点b。然后我们可以让fmap f
将三角形a
变换为三角形b
。 (如果我正确理解你的意图,请观察你正在将f
应用于 9 个对象)[编辑:是 27]In the Triangle instance,
f
isa -> b
. We have to convert it toPoint a -> Point b
first. Then we can makefmap f
transformTriangle a
toTriangle b
. (Observe you're applyingf
to 9 objects, if I understood your intention correctly) [edit: was 27]