创建haskell IO包装器

Ed *_*ehn 3 haskell io-monad

在关于FFI的GHC手册部分中,声明程序员可以使用newtype在IO monad周围创建一个包装器monad,并在调用外部代码时使用它来代替IO monad.(GHC手册)

到目前为止,我有:

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
Run Code Online (Sandbox Code Playgroud)

关于如何实施(>>=)和实施,我感到很茫然(>>).

bra*_*drn 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)
Run Code Online (Sandbox Code Playgroud)

但是,这还不够,因为Haskell需要实例,Functor并且可以在定义实例Applicative之前和之前Monad.一个更简单的解决方案是将文件放在{-# LANGUAGE GeneralizedNewtypeDeriving #-}文件的顶部(或:set -XGeneralizedNewtypeDeriving在GHCi中启用),这样就可以实现这一点;

newtype PGm a = PGm (IO a) deriving (Functor, Applicative, Monad)
Run Code Online (Sandbox Code Playgroud)

我们的想法是,如果启用此扩展,GHC将足够智能,可以从"基础"实例中自动派生新类型实例.