具有两个构造函数的数据类型上的函子-发生检查



我有一个数据类型

data Pnt2d i v = Pnt2d {_p2id:: i, _v2:: V2 v}

并且想要构造函子以应用于作为的第二分量(V2(

instance Functor (Pnt2d i) where 
fmap f (Pnt2d i v) = Pnt2d i (f v)

但我得到了一个";发生检查";。我知道我只能在多参数数据类型的第二个参数上构建Functor,这里就是这样。特殊的是,第二个类型参数是内部(V2(类型的类型参数,这可能是错误的原因。这似乎与使用数据内部的数据时的Functor错误有关:;不能构造无限类型";当单独编写时,我检查了函子的类型,它似乎是正确的。在编写fmap时遇到问题的答案表明,两个嵌套函子是必要的——这里是这样吗?

我不知道在这种情况下如何构造函子。我试过使用Lenses,但没有效果,我很想看看有/没有使用Lensess的解决方案是什么。

src/Uniform/Point2d.hs:119:35: error:
• Occurs check: cannot construct the infinite type: b ~ V2 b
• In the second argument of ‘Pnt2d’, namely ‘(f v)’
In the expression: Pnt2d i (f v)
In an equation for ‘fmap’: fmap f (Pnt2d i v) = Pnt2d i (f v)
• Relevant bindings include
f :: a -> b (bound at src/Uniform/Point2d.hs:119:10)
fmap :: (a -> b) -> Pnt2d i a -> Pnt2d i b
(bound at src/Uniform/Point2d.hs:119:5)
|
119 |     fmap f (Pnt2d i v) = Pnt2d i (f v)
|                                   ^^^
src/Uniform/Point2d.hs:119:37: error:
• Occurs check: cannot construct the infinite type: a ~ V2 a
• In the first argument of ‘f’, namely ‘v’
In the second argument of ‘Pnt2d’, namely ‘(f v)’
In the expression: Pnt2d i (f v)
• Relevant bindings include
v :: V2 a (bound at src/Uniform/Point2d.hs:119:21)
f :: a -> b (bound at src/Uniform/Point2d.hs:119:10)
fmap :: (a -> b) -> Pnt2d i a -> Pnt2d i b
(bound at src/Uniform/Point2d.hs:119:5)
|
119 |     fmap f (Pnt2d i v) = Pnt2d i (f v)

在您的实例中,f的类型为a -> b,但您使用它时就好像它的类型是V2 a -> V2 b一样。

您需要使用fmap提升f,以便它具有您想要的类型。

instance Functor (Pnt2d i) where 
fmap f (Pnt2d i v) = Pnt2d i (fmap f v)

有了镜头,你可以做到:

instance Functor (Pnt2d i) where 
fmap f = v2 %~ fmap f

最新更新