gpt4 book ai didi

haskell - 在任意 monad 中带有解释器的操作 monad

转载 作者:行者123 更新时间:2023-12-03 14:18:55 27 4
gpt4 key购买 nike

我正在使用 operational monad作者:海因里希·阿普菲尔姆斯。
我想用结果类型的 monad 参数化解释器。
我的代码的以下版本编译:

{-# LANGUAGE GADTs #-}

import Control.Monad.Operational

data EloI a where
Display :: Int -> EloI ()

type Elo a = Program EloI a

interpret :: Monad m => (Int -> m ())
-> Elo a
-> Int
-> m a
interpret display = interp
where
interp :: Monad m => Elo a -> Int -> m a
interp = eval . view
eval :: Monad m => ProgramView EloI a -> Int -> m a
eval (Display i :>>= is) s = interp (is ()) s

现在我将最后一行更改为
eval (Display i :>>= is) s = display i >> interp (is ()) s

并且类型推断不再成功,我得到了输出

无法从上下文中推导出 (m ~ m1) (Monad m)
受解释的类型签名约束::Monad m => (Int -> m ()) -> Elo a -> Int -> m a
(……)

当我删除 interp 的类型签名时,我收到一个额外的错误(无法推断 (a1 ~ a))。
当我将所有 m 更改为 IO (就像在操作 monad 的井字游戏示例中一样)时,它会再次编译。
我是在尝试没有意义的东西,还是可以向 GHC 提供一些提示?我不得不承认我不确定我是否需要这种灵活性。

最佳答案

那是因为 m在本地类型签名中是新的类型变量,因此它们 promise 可以与任何 Monad 一起使用。如果您使用 display , eval仅适用于特定的 monad display使用。如果您 a) 删除本地类型签名,或 b) 带上类型变量 m,它应该可以工作。进入范围

{-# LANGUAGE ScopedTypeVariables #-}
...
interpret :: forall m. (Int -> m ()) -> Elo a -> Int -> m a

关于haskell - 在任意 monad 中带有解释器的操作 monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8372061/

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