gpostpro如何"escape from the monad"?
How does gpostpro "escape from the monad"?
我想了解 Haskell recursion-schemes
包中这个非常抽象的递归函数是如何工作的(或者,实际上,它做了什么!)- 来自 this file:
class Functor (Base t) => Corecursive t where
[...]
-- | A generalized postpromorphism
gpostpro
:: (Recursive t, Monad m)
=> (forall b. m (Base t b) -> Base t (m b)) -- distributive law
-> (forall c. Base t c -> Base t c) -- natural transformation
-> (a -> Base t (m a)) -- a (Base t)-m-coalgebra
-> a -- seed
-> t
gpostpro k e g = a . return where a = embed . fmap (ana (e . project) . a . join) . k . liftM g
特别是,我想了解的是:它如何应用提到 monad 类型构造函数 m
的 g
函数,然后 return t
类型,哪个没有提到或依赖m
?我认为在 Haskell!
中逃避任意单子是不可能的
我首先将源文件加载到 Intero 中以尝试使用其点类型功能,但那次尝试 failed。
然后我使用 cabal repl
将其加载到 GHCi 中,并尝试通过组合函数一次一个地跟踪类型,使用 GHCi 通过注释掉定义的各个位来帮助进行类型推断。但是,当我到达 fmap
时,我不知道要注释掉什么,因为如果我取消注释递归 a
调用但注释掉其他内容,我认为它甚至可能不会编译,因为 a
的部分注释掉的 definition 没有正确的类型。
我设法让 ghci 告诉我子表达式的类型,方法是将它们包围在 (
...:: _)
.
中
事实证明,诀窍是 "distributive law" k
允许您将 monad 推入临时 Base
类型,然后 embed
方法允许您免除临时 Base
类型并返回 t
。例如,如果具体类型 t
确实没有提到 IO
,那么就不可能为 IO monad 编写这样的 k
(安全地)。所以这里没有魔法——也就是说,没有办法使用这个函数来逃避 monads,否则 monads 是无法逃避的,比如 IO。
我想了解 Haskell recursion-schemes
包中这个非常抽象的递归函数是如何工作的(或者,实际上,它做了什么!)- 来自 this file:
class Functor (Base t) => Corecursive t where
[...]
-- | A generalized postpromorphism
gpostpro
:: (Recursive t, Monad m)
=> (forall b. m (Base t b) -> Base t (m b)) -- distributive law
-> (forall c. Base t c -> Base t c) -- natural transformation
-> (a -> Base t (m a)) -- a (Base t)-m-coalgebra
-> a -- seed
-> t
gpostpro k e g = a . return where a = embed . fmap (ana (e . project) . a . join) . k . liftM g
特别是,我想了解的是:它如何应用提到 monad 类型构造函数 m
的 g
函数,然后 return t
类型,哪个没有提到或依赖m
?我认为在 Haskell!
我首先将源文件加载到 Intero 中以尝试使用其点类型功能,但那次尝试 failed。
然后我使用 cabal repl
将其加载到 GHCi 中,并尝试通过组合函数一次一个地跟踪类型,使用 GHCi 通过注释掉定义的各个位来帮助进行类型推断。但是,当我到达 fmap
时,我不知道要注释掉什么,因为如果我取消注释递归 a
调用但注释掉其他内容,我认为它甚至可能不会编译,因为 a
的部分注释掉的 definition 没有正确的类型。
我设法让 ghci 告诉我子表达式的类型,方法是将它们包围在 (
...:: _)
.
事实证明,诀窍是 "distributive law" k
允许您将 monad 推入临时 Base
类型,然后 embed
方法允许您免除临时 Base
类型并返回 t
。例如,如果具体类型 t
确实没有提到 IO
,那么就不可能为 IO monad 编写这样的 k
(安全地)。所以这里没有魔法——也就是说,没有办法使用这个函数来逃避 monads,否则 monads 是无法逃避的,比如 IO。