【发布时间】:2015-08-29 00:07:30
【问题描述】:
我已经定义了一个类型X为
newtype X i o = X { runX :: Int -> i -> IO o }
我已经创建了Functor、Applicative 和Monad 的实例
instance Functor (X i) where
fmap f a = X $ \ i o -> liftA f $ runX a i o
instance Applicative (X i) where
pure x = X $ \ _ _ -> return x
a <*> b = X $ \ i o -> liftA2 (<*>) (runX a i o) (runX b i o)
instance Monad (X i) where
return = pure
a >> b = X $ \ i o -> runX a i o >> runX b i o
您可能会说,到目前为止,我一直无法为>>= 定义一个定义,因此将其排除在外。我预计这会在编译时出错,但实际上,它所做的只是发出警告。很好,所以它不会检查一个类的所有方法是否都已定义,但我确实不能使用 >>=。不对,又错了。令我惊讶的是,GHCi 很高兴地评估了let x = pure 5 >>= pure。 Control.Monad没有导出>>=的默认定义,我当然也没有定义,这怎么可能?
【问题讨论】:
-
我无法让您的
Functor实例进行类型检查。它抱怨它无法将类型IO (f0 a)与i0 -> IO o0匹配。 -
发布的代码无法编译(例如,在
fmap定义中应该是runX a i o)。也许您在这里粘贴了错误的版本? -
这对我仍然不起作用,但取出
liftA可以。 -
仍然不进行类型检查。我认为您不需要
fmap定义中的fmap,也不需要(<*>)定义中的liftA2。如果我删除它们,它会进行类型检查并收到您描述的警告。 -
我相信 GHC 确实会发出 警告。但它可能需要使用
-Wall选项进行编译。此外,如果您定义了一个类,您可以使用MINIMAL来准确地告诉编译器该实例应该提供哪些方法。通过这种方式,您可以提供相互递归的默认实现,并且仍然让编译器知道必须至少实现这两种方法中的一种才能使事情正常进行。
标签: haskell monads typeclass type-systems