使用数据内部数据时的Functor错误:"无法构造无限类型"

Mik*_*cki 1 haskell types

在了解Haskell的类型系统的同时,我遇到了这个玩具问题.当我编译以下代码时:

data SingleData a = SingleData a Int String -- etc.
data DataFail a = DataFail [SingleData a]
instance Functor DataFail where
    fmap f (DataFail xs) = DataFail (map f xs)
Run Code Online (Sandbox Code Playgroud)

我得到了可怕的"发生检查:无法构造无限类型:b = SingleData b"消息对fmap的定义.奇怪的是,如果fmap在实例声明之外,它的相同定义将起作用:

fmapWorks f (DataFail xs) = DataFail (map f xs)
Run Code Online (Sandbox Code Playgroud)

更奇怪的是,实现Monoid编译并且工作得很好:

instance Monoid (DataFail a) where
    mempty = DataFail []
    mappend (DataFail xs) (DataFail ys) = DataFail (xs ++ ys)
Run Code Online (Sandbox Code Playgroud)

我相信这在某种程度上是在DataFail中使用SingleData的结果,因为这也可以正常工作:

data DataSuccess a = DataSuccess [a]
instance Functor DataSuccess where
    fmap f (DataSuccess xs) = DataSuccess (map f xs)
Run Code Online (Sandbox Code Playgroud)

为什么Haskell抱怨DataFail的fmap函数,我该怎么做才能修复它?

iva*_*anm 8

"发生检查"错误并不是那么可怕......

问题是提供的功能fmap.试试这个:

instance Functor SingleData where
  fmap f (SingleData a i s) = SingleData (f a) i s

instance Functor DataFail where
  fmap f (DataFail sds) = DataFail $ map (fmap f) sds
Run Code Online (Sandbox Code Playgroud)

所以,实际错误是你的用法map:类型不匹配. Functor期望它是类型a -> b,但你使用它的方式是类型SingleData a -> SingleData b; 额外的Functor实例SingleData允许您使用fmap将函数直接应用于其中的值.