在关于FFI的GHC手册部分中,声明程序员可以使用newtype
在IO monad周围创建包装器monad,并在调用外来代码时使用它代替IO monad。 (GHC manual)
到目前为止,我有:
newtype PGm a = PGm (IO a)
instance Monad PGm where
(>>=) a b = ...
(>>) a b = ...
return a = PGm (return a) --I think
fail a = PGm (fail a) --I think
我不知道如何实现(>>=)
和(>>)
。
答案 0 :(得分:7)
您只需解开并重新包装每个操作。困难的部分是弄清楚展开和重新包装的位置:
newtype PGm a = PGm (IO a)
instance Monad PGm where
(>>=) (PGm a) b = PGm (a >>= (unPGm . b))
where
unPGm (PGm x) = x
(>>) (PGm a) (PGm b) = a >> b
return a = PGm (return a)
fail a = PGm (fail a)
但是,这还远远不够,因为Haskell在定义Functor
实例之前需要Applicative
和Monad
的实例。一个更简单的解决方案是将{-# LANGUAGE GeneralizedNewtypeDeriving #-}
放在文件的顶部(或在GHCi中启用:set -XGeneralizedNewtypeDeriving
),这使您可以做到这一点;
newtype PGm a = PGm (IO a) deriving (Functor, Applicative, Monad)
想法是,如果启用此扩展,GHC将足够聪明,可以自动从其“基础”实例派生新类型实例。