鉴于以下内容,取自Typeclassopedia:
class MyApplicative f where
pure :: a -> f a
ap :: f (a -> b) -> f a -> f b
instance Monoid e => MyApplicative ((,) e) where
pure x = (mempty, x)
(u, f) `ap` (v, x) = (u `mappend` v, f x)
我尝试做类似的事情:
ghci> (+) <$> Control.Applicative.pure 100 <*> Control.Applicative.pure 50
150
但是,使用新定义的Applicative
:
ghci> Main.pure (+ 100) `ap` (Main.pure 50)
<interactive>:132:1:
No instance for (MyApplicative f0) arising from a use of `it'
The type variable `f0' is ambiguous
Note: there is a potential instance available:
instance Monoid e => MyApplicative ((,) e)
-- Defined at MonoidWork.hs:8:10
In the first argument of `print', namely `it'
In a stmt of an interactive GHCi command: print it
查看类型:
ghci> :t Main.pure (+ 100)
Main.pure (+ 100) :: (MyApplicative f, Num a) => f (a -> a)
和
ghci> :t (Main.pure 50)
(Main.pure 50) :: (MyApplicative f, Num a) => f a
我不明白如何解决编译时错误。
答案 0 :(得分:5)
你只需要给它一个类型签名。 GHC / GHCi有一些特殊的规则来默认某些类型类型的帮助,特别是当你在GHCi中时。否则,您必须始终执行1 + 2 :: Int
之类的操作,而不仅仅是1 + 2
。如果你给它一个类型签名,它就可以正常工作:
> Main.pure (+ 100) `ap` Main.pure 50 :: ((), Int)
((), 150)
GHC对你自己定义的类型类没有默认规则(并允许这样的行为很难做到正确,否则你的程序会产生意想不到的结果)。