在关于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)
关于如何实施(>>=)和实施,我感到很茫然(>>).
您只需打开并重新打开每个操作.困难的部分是弄清楚展开和重新封装的位置:
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将足够智能,可以从"基础"实例中自动派生新类型实例.