GHC 不知道如何显示类型 a。
data FunctorExample a = FunctorExample { val1 :: a,
val2 :: String
} deriving (Show)
instance Functor FunctorExample where
fmap f (FunctorExample x y) = FunctorExample (f x) (y ++ " " ++ show x)
Run Code Online (Sandbox Code Playgroud)
我尝试了很多事情,包括:在数据中设置类型约束(现已弃用),并使用 {-# LANGUAGE InstanceSigs #-} 为 fmap 添加约束并添加下面建议的类型签名,但没有成功(虽然我的类型签名可能有缺陷......)。
* No instance for (Show a) arising from a use of `show'
Possible fix:
add (Show a) to the context of
the type signature for:
fmap :: forall a b.
(a -> b) -> FunctorExample a -> FunctorExample b
Run Code Online (Sandbox Code Playgroud)
是否没有将 a 限制为 Show 实例的标准方法?在我的用法中,它碰巧总是一个 Int 。
免责声明:如果我犯了任何错误或以不同的方式处理问题,请原谅我,我自己也是 Haskell 学习者。
我想指出的第一件事是你的定义fmap不符合两个函子定律。这些规律的存在使得“行为fmap仍然是可预测的”。
第一定律指出fmap id functor应该与id functor(即fmap id = id)没有区别。只需观察定义,我们就可以看到:
fmap id (FunctorExample x y) = FunctorExample (id x) (y ++ ...)
Run Code Online (Sandbox Code Playgroud)
...不会飞,因为第二个的值y很容易改变。
第二定律指出fmap (f . g) = fmap f . fmap g。我将把它留给你作为练习来检查它是否符合。
我在这里建议的是使用不同的函数,这样就没有遵守函子定律的负担。这样,您就可以使用类型类约束。
propagate :: Show a => (a -> b) -> FunctorExample a -> FunctorExample b
propagate f (FunctorExample x y) = FunctorExample (f x) (y ++ " " ++ show x)
Run Code Online (Sandbox Code Playgroud)
现在,也许您对fmap. 我不完全确定。也许您打算FunctorExample在其他带有函子的函数中使用。(我猜是这个名字。)如果是这样,请考虑重新设计fmap定义,使其符合函子定律。
澄清一下,限制 的类型fmap 是不可能的。