gpt4 book ai didi

haskell - 为嵌套的 monadic 类型实现 Monad 实例

转载 作者:行者123 更新时间:2023-12-04 00:56:39 25 4
gpt4 key购买 nike

作为 Haskell 自学练习的一部分,我正在尝试为我的类型派生一个 Monad 实例。类型定义为:

newtype ParsePackUnpack f a = ParsePackUnpack
{
unparse:: State PackUnpackState (Ap f a)
}

其中 Ap f a 来自 Data.Monoid。对于我的类型,我试图说解析是一个有状态的操作,结果是任何 monoid

到目前为止,我已经成功地通过提升实现了这个 3 级深度类型的 FunctorApplicative 实例:

instance Functor f => Functor (ParsePackUnpack f) where
fmap f ma =
let f' = fmap f -- lift (a -> b) to (Ap f a -> Ap f b)
in ParsePackUnpack $ f' <$> (unparse ma)

instance Applicative f => Applicative (ParsePackUnpack f) where
pure = ParsePackUnpack . pure . pure

f <*> ma =
let f' = liftA2 (<*>) . unparse $ f -- lift Ap f (a -> b) -> Ap f a -> Ap f b to State s (Ap f a) -> State s (Ap f b)
in ParsePackUnpack $ f' (unparse ma) -- Apply to State s (Ap f a)

但是我无法为我的类型正确派生 Monad 实例。经过一些类型的打高尔夫球,这是我最近的尝试:

instance Monad f => Monad (ParsePackUnpack f) where
return = ParsePackUnpack . return . return

ma >>= f = ParsePackUnpack . state $ \st ->
let (a, s) = runState (unparse ma) st
res = a >>= fst . flip runState s . unparse . f -- fst ignores state from the result
in (res, s)

我认为这是不正确的,因为我忽略了 res 操作的状态。

为我的类型实现 >>= 操作的正确方法是什么?由于这是一个学习练习,我试图避免使用 Monad 转换器。如果 Monad 变形金刚是可行的方法,您能否也解释一下为什么会这样?

最佳答案

Monad 的组合不如应用程序好。虽然 f (g a) 是一个应用程序,只要 fg 是(因此您可以编写应用程序实例),但它通常不是fg 是 monad 时的 monad。这就是为什么我们需要 monad 转换器而不是应用转换器。

这是一个相关的练习。忘记使用库中的 State,让我们手动处理它的表示。 State s (IO a) 展开为 s -> (IO a, s)。要实现绑定(bind),您将获得

f :: s -> (IO a, s)
g :: a -> s -> (IO b, s)

你能想出如何将第一个提供给第二个,通过“有状态”传递 s 吗?

bound :: s -> (IO b, s)
bound s0 = ??

试一试。 (剧透)在你确信这是不可能的之后,想想是什么让它不可能,以及你需要如何修改类型才能让它成为可能。然后使用该模式定义一个“StateIO s”monad。

关于haskell - 为嵌套的 monadic 类型实现 Monad 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61982584/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com