gpt4 book ai didi

haskell - 什么是更自由的单子(monad)?

转载 作者:行者123 更新时间:2023-12-04 18:10:55 25 4
gpt4 key购买 nike

这个词我听过几次,但我仍然不知道究竟什么是所谓的“Freer Monad”。这个名字让我想到了 Free Monads,但我看不出它们实际上是如何相关的。我在 hackage 上找到了一些库:http://hackage.haskell.org/package/freer ,但那里的例子对我没有多大帮助。
我根本不理解这个想法,因此我看不到它们有什么好的用例。我还想知道它们比免费的 monad 和经典的 mtl 堆栈有什么优势。

最佳答案

我知道这是一个旧线程,但我想我还是会回答它以防万一

what [...] is a so-called "Freer Monad"


根据原论文 Freer Monads, More Extensible Effects “Freer Monad”本质上是一个 Free Monad,没有 Free Monad 的必要 Functor 约束。
自由单子(monad)基本上是单子(monad)结构的本质; “最小”的东西仍然是一个单子(monad)。一个很好的实用解释方法 can be found in this article .这篇文章还展示了“正常”的自由 monad 需要一个 Functor 约束。
然而,在每个函数中添加仿函数约束通常是相当乏味的(有时实现起来可能很奇怪),事实证明,通过“移动仿函数功能”到 Impure 的参数。构造函数,以便实现方可以更改输出本身的类型(因此没有通用仿函数),可以摆脱这个约束。这是通过使用 GADTs 来完成的。 : (来自 Freer Monads 论文的示例)
data Free f a = Pure a
| Impure (f (Free f a))

instance Functor f => Monad (Free f) where
变成
data FFree f a where
Pure :: a → FFree f a
Impure :: f x → (x → FFree f a) → FFree f a

instance Monad (FFree f) where
[...]
Impure fx k’ >>= k = Impure fx (k’ >>> k)
这基本上让后面的实现选择如何执行 fmap操作将 [双关语无意] 固定为适当的“输出/包装类型”。
所以根本的区别本质上是可用性和通用性。
由于有些困惑: FFree是 Freer monad,对应于 Eff包装内 freer-simple .

good usecases for them


Freer monads 和 Free monads 一样适合构建 DSL。
例如考虑一个类型
data Lang r where
LReturn :: Var -> Lang Int
LPrint :: IntExpr -> Lang ()
LAssign :: Var -> IntExpr -> Lang ()
LRead :: Var -> Lang Int

这告诉我在 Lang 中有几个操作要执行。 : return x print x assign x y read y .
我们在这里使用 GADT,以便我们还可以指定各个操作将具有的输出。如果我们在 DSL 中编写函数,这会非常方便,因为可以检查它们的输出。
添加一些便利功能(可以实际派生):
lReturn :: Member Lang effs
=> Var -> Eff effs Int
lReturn = send . LReturn

lPrint :: Member Lang effs
=> IntExpr -> Eff effs ()
lPrint = send . LPrint

lAssign :: Member Lang effs
=> Var -> IntExpr -> Eff effs ()
lAssign v i = send $ LAssign v i

lRead :: Member Lang effs
=> Var -> Eff effs Int
lRead = send . LRead

(这已使用 freer 编写)
现在我们可以像这样使用它们:(假设 IntExpr 包含变量和整数)
someFunctionPrintingAnInt = do
lAssign (Var "a") (IE_Int 12)
lPrint (IE_Var $ Var "a")
这些功能现在使您能够拥有可以以不同方式解释的 DSL。为此,只需要一个具有 effs 特定类型的解释器即可。 (这是 ~~ 一个更自由的单子(monad)“实例”的类型级别列表)
所以 freer采用更自由的单子(monad)的想法并将其打包到效果系统中。
这个解释器可能看起来像这样:
runLangPure :: Eff '[Lang] Int -> Either () Int -- [StateMap]
runLangPure program = fst . fst $
run (runWriter (runState empty (runError (reinterpret3 go program))))
where
go :: Lang v -> Eff '[Error (), State StateMap, Writer [String]] v
go (LReturn var) = get >>= go (Eval stmt) >>= tell . []
go (LPrint expr) = do
store <- get
value <- evalM expr
tell [show value]
go (LAssign var expr) = do
value <- evalM expr
--modify state (change var)
go (LRead var) = do
strValue <- getLine
get >>= insert var (stringToInt strValue)

run...部分指定单子(monad)的初始“状态”。 go部分是解释器本身,解释不同的可能 Action 。
请注意,可以使用函数 gettell在同一个 do block 中,即使它们是不同 monad 的一部分,这使我们

I also wonder what advantages do they provide over free monads and classic mtl stacks.


该实现允许在不使用 lift 的情况下使用“monad stack”不同部分的单子(monad)操作ing。
关于实现:
为了理解这一点,我们从高度抽象的角度来看待它:
我们DSL的辅助功能是 sendEff effs需要 Member Lang effs .
所以 Member约束只是声明 Lang 的一种方式在类型级别列表中 effsMember Lang effs . (基本上类型级别 elem ) Eff monad 具有“询问” Member 的功能。单子(monad)的类型级别列表的 s 是否可以处理当前值(请记住,操作只是随后解释的值)。如果是,则执行他们的解释,如果不是,则将问题移交给列表中的下一个 monad。
freer-simple 中花费一些时间后,这将变得更加直观和易于理解。代码库。

关于haskell - 什么是更自由的单子(monad)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57758951/

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