Haskell 围绕IO创建包装器Monad
假设我想创建一个执行IO操作的包装Monad,并将其包装如下。sequence操作符(>>)工作得很好,但是我很难实现Haskell 围绕IO创建包装器Monad,haskell,io,monads,Haskell,Io,Monads,假设我想创建一个执行IO操作的包装Monad,并将其包装如下。sequence操作符(>>)工作得很好,但是我很难实现返回和>= 我尝试了return x=DelayedAction(return x),但没有得到正确的类型 newtype DelayedAction a = DelayedAction {action :: IO a} instance Functor DelayedAction where fmap = liftM instance Applicative Delay
返回
和>=
我尝试了return x=DelayedAction(return x)
,但没有得到正确的类型
newtype DelayedAction a = DelayedAction {action :: IO a}
instance Functor DelayedAction where
fmap = liftM
instance Applicative DelayedAction where
pure = return
(<*>) = ap
instance Monad DelayedAction where
return x = undefined
(DelayedAction firstIO) >>= f = undefined
(DelayedAction firstIO) >> (DelayedAction secondIO) =
DelayedAction
( do
firstIO
threadDelay 1000000
secondIO
)
newtype DelayedAction a=DelayedAction{action::IO a}
实例函子DelayedAction,其中
fmap=liftM
实例应用程序延迟动作,其中
纯=返回
()=ap
实例Monad DelayedAction,其中
返回x=未定义
(DelayedAction firstIO)>>=f=未定义
(DelayedAction firstIO)>>(DelayedAction secondIO)=
延迟行动
(做
第一
线程延迟1000000
第二
)
@Aplet123和@leftaroundabout澄清,这不可能是真正的单子,因为它不能遵循单子定律。尽管如此,我还是想出了一个令编译器满意的解决方案。教了我很多关于单子、类型类、类型、do符号等的知识
instance Monad DelayedAction where
return x = DelayedAction (return x)
da >>= f =
DelayedAction
( do
firstIOValue <- action da
threadDelay 1000000
(action . f) firstIOValue
)
这不符合单子定律。如果每次绑定都添加延迟,
m>=return
将不等于m
。另见:和。这并不是说写一个实现是不可能的,只是意味着你不应该这样做。但是,在这种情况下,可以通过在每个操作(返回除外)中设置延迟来解决此问题。实现这一点的最实际的方法是批量复制monad实例,但不导出DelayedAction
构造函数,而只导出DelayedAction a=threadDelay 1000000>>a
@leftaroundabout-这很有趣,可以扩展吗?“批量复制monad实例”是什么意思?
da >>= f =
DelayedAction
( action da >>= (\firstIOValue -> threadDelay 1000000 >> (action . f) firstIOValue)