我找不到任何不简单地丢弃内部容器状态的可能实例。这并不奇怪,因为绑定到数据的纯函数的返回应该在每次调用输入时返回相同的内容,无论之前是否调用过,您在评论中暗示了这一点。
通过它自己
Monad
我能想到的唯一实例都丢弃了内部容器的后续状态。
instance Monad (SF e) where
return a = SF . const $ (a, return a)
(>>=) sa f = SF go
where
go e =
let
(a, sa') = run sa e
sb = f a
(b, _) = run sb e
in
(b, sa' >>= f)
或者
join :: SF e (SF e a) -> SF e a
join ssa = SF go
where
go e =
let
(sa, ssa') = run ssa e
(a, _) = run sa e
in
(a, join ssa')
这些可以使用函数的 Monad 实例更简洁地表达
instance Monad (SF e) where
return a = SF . const $ (a, return a)
(>>=) sa f = SF {
run =
do
(a, sa') <- run sa
(b, _) <- run (f a)
return (b, sa' >>= f)
}
我们可以在别处寻找一些不同的东西。
函数单子实例
您newtype SF e a = SF { run :: e -> (a, SF e a) }
非常接近从 to 的e
功能a
。对于函数的 Monad 实例,唯一明智>>=
的做法是将参数同时传递给内部函数和外部函数。这是我们已经提出的。让我们看看能不能想出别的办法。
状态T
您的代码有点类似于应用于函数的 Monad 实例的StateT monad 转换器。不幸的是,这并没有产生我们正在寻找的东西。
考虑以下(StateT monad 转换器):
newtype StateT s m a = StateT { runStateT :: s -> m (a, s)}
应用于((->) e)
接受参数的函数的类型 `e.
StateT s ((->) e) a
有一个构造函数StateT { runStateT :: s -> e -> (a, s) }
。
这与您的类型不同,因为必须提供初始状态,并且显式跟踪状态,而不是已经包含在返回的下一个值中。让我们看看这个Monad
实例是什么。StateT
的Monad
实例是
instance (Monad m) => Monad (StateT s m) where
return a = state $ \s -> (a, s)
m >>= k = StateT $ \s -> do
~(a, s') <- runStateT m s
runStateT (k a) s'
state f = StateT (return . f)
结合一个实例(->) e
instance Monad ((->) e) where
return = const
(>>=) x y z = y (x z) z
我们将得到以下内容,其中do
将工作转储到 ((->) e) 的实例上
instance Monad (StateT s ((->) e) where
return a = StateT (const . (\s -> (a, s)))
m >>= k = StateT $ \s e ->
let (a, s`) = runStateT m s e
in runStateT (k a) s` e
这看起来完全不同。我们不会丢失任何州的历史。这里发生的事情是内部容器的状态从外部容器传递给它,并且两个容器必须具有相同的类型才能使状态工作。这根本不是我们想要的。
新鲜玩意
如果我们尝试使用StateT
您的类型制作类似的东西会发生什么?我们希望能够传入类型(->) e
并获得像您这样的结构。我们将创建一个名为SFT m a
such 的东西,SFT ((-> e) a
它的结构与SF e a
.
newtype SF e a = SF { run :: e -> (a, SF e a)
newtype SFT m a = SFT { unSFT :: m (a, SFT m a) }
我们可以用 apply SFT
to替换(->) e)
为SF
applied toe
SF e a -- is replaced by
SFT ((->) e) a
这有一个构造函数
SF { run :: e -> (a, SF e a) }
SFT { unSFT :: e -> (a, SFT ((->) e) a) }
这没有提供新的见解,我能想到的唯一Monad
实例几乎与原始实例相同。
instance Monad m => Monad (SFT m) where
return a = SFT . return $ (a, return a)
(>>=) sa f = SFT {
unSFT =
do
(a, sa') <- unSFT sa
(b, _) <- unSFT (f a)
return (b, sa' >>= f)
}