Haskell gpostpro是如何实现的;逃离单子;?

Haskell gpostpro是如何实现的;逃离单子;?,haskell,recursion,monads,recursion-schemes,Haskell,Recursion,Monads,Recursion Schemes,我试图了解Haskell递归方案包中的这个非常抽象的递归函数是如何工作的(或者,实际上,它是如何工作的!)-来自: 特别是,我想了解的是:它如何应用提到monad类型构造函数的g函数m,然后返回t类型的值,该值没有提到或依赖于m?我以为在哈斯凯尔逃脱独断的单子是不可能的 我首先将源文件加载到Intero中,以尝试使用其点类型功能,但没有尝试 然后,我使用cabal repl将其加载到GHCi中,并尝试通过组合函数一次一个地跟踪类型,使用GHCi通过注释出定义的各个位来帮助进行类型推断。然而,当我

我试图了解Haskell
递归方案
包中的这个非常抽象的递归函数是如何工作的(或者,实际上,它是如何工作的!)-来自:

特别是,我想了解的是:它如何应用提到monad类型构造函数的
g
函数
m
,然后返回
t
类型的值,该值没有提到或依赖于
m
?我以为在哈斯凯尔逃脱独断的单子是不可能的

我首先将源文件加载到Intero中,以尝试使用其点类型功能,但没有尝试


然后,我使用
cabal repl
将其加载到GHCi中,并尝试通过组合函数一次一个地跟踪类型,使用GHCi通过注释出定义的各个位来帮助进行类型推断。然而,当我到达
fmap
时,我无法确定要注释什么,因为如果我取消了递归
a
调用的注释,但注释掉了其他内容,我认为它甚至可能无法编译,因为部分注释掉的
a
的定义没有正确的类型。

我设法让ghci告诉我子表达式的类型,方法是将它们包围在
::)


事实证明,诀窍是,“分配法则”
k
允许您将monad推入临时
Base
类型中,然后
embed
方法允许您放弃临时
Base
类型并返回到
t
。例如,如果具体类型
t
没有提到
IO
,那么就不可能(安全地)为IO monad编写这样的
k
。因此,这里没有魔法——也就是说,没有任何方法可以使用此函数从单子中逃脱,否则单子将无法逃脱,如IO。

您可以放置
而不是任何表达式来询问GHC的类型。并且。转义:
t
属于
Recursive
类,这意味着它有
*->*
类。这暗示gpospro返回类型没有转义任何内容,而是被包装成了某种内容。这可能是一个单子。@arrowd如果是这样的话,上面的类型签名将是不可能的,因为您不能有一个返回类型具有kind
*->*
。然后将您自己的答案标记为答案。
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