在了解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函数,我该怎么做才能修复它?
"发生检查"错误并不是那么可怕......
问题是提供的功能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将函数直接应用于其中的值.