我定义了一个类型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
没有导出>>=
的默认定义,我也肯定没有定义它,所以这怎么可能呢?
liftA
就可以了。 - Tikhon JelvisliftA2
太多了 :P - Ørjan Johansen-Wall
选项进行编译。此外,如果您定义了一个类,可以使用MINIMAL
来告诉编译器实例应该提供哪些方法。通过这种方式,您可以提供相互递归的默认实现,同时让编译器知道必须实现其中至少一个方法才能使事情正常工作。 - Bakuriu