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

kq0g1dla  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(126)

我有一个数据类型

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 error when using a data inside a data: "cannot construct the infinite type"有关。我检查了函子的类型,当单独编写时,它似乎是正确的。Having trouble writing my fmap中的答案表明两个嵌套函子是必要的-这里是不是这样?
我不知道,如何构造函子在这种情况下。我尝试与镜头,但无济于事,并会有兴趣看看解决方案是什么与/不使用镜头。

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)
mec1mxoz

mec1mxoz1#

在您的示例中,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

相关问题