创建 haskell 个 IO 包装器

Create haskell IO wrapper

在 GHC 手册关于 FFI 的部分中,声明程序员可以使用 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

我不知道如何实施 (>>=)(>>)

您只需打开并重新包装每个操作。困难的部分是弄清楚展开和重新包装的位置:

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 需要 FunctorApplicative 的实例才能定义 Monad 实例。一个更简单的解决方案是将 {-# LANGUAGE GeneralizedNewtypeDeriving #-} 放在文件的顶部(或在 GHCi 中启用 :set -XGeneralizedNewtypeDeriving),这样你就可以这样做;

newtype PGm a = PGm (IO a) deriving (Functor, Applicative, Monad)

想法是,如果您启用此扩展,GHC 将足够智能,可以自动从 'base' 实例派生新类型实例。