为什么 Djinn 无法实现常见的 monadic 函数?

Why does Djinn fail to realize common monadic functions?

我最近偶然发现了 Djinn 并短暂地使用它来尝试看看它是否对我的日常编码工作流程有用。我很高兴看到 Djinn 有 monad 并试图看看它是否能够找到一些很酷的函数。

巨灵确实创造了一些奇迹。最初(至少对我而言)不直观的函数 >>= (>>=) 的类型签名是 Monad m => ((a -> m b) -> m a) -> (a -> m b) -> m b。 Djinn 能够通过声明

立即揭开这个神秘面纱
Djinn> f ? Monad m => ((a -> m b) -> m a) -> (a -> m b) -> m b
f :: (Monad m) => ((a -> m b) -> m a) -> (a -> m b) -> m b
f a b = a b >>= b

不幸的是,尽管知道 Monad 类型类,但 Djinn 似乎无法在 monad 上找到其他标准函数。

Djinn 知道如何使用 \ 构造匿名函数,为什么会这样?

我的粗略怀疑是,也许 Djinn 对类型类有一个简单化的概念,并以某种方式将 m a 视为 "fixed",因此 m (a, b) 不会被视为 [=25= 的情况],但我不知道如何使它比当前的手波浪形式更具体,或者这种直觉是否正确。

支持类型 类 看起来很像支持 rank-2 类型;比较:

join :: Monad m
     => m (m a) -> m a

对比:

join :: (forall a. a -> m a)
     -> (forall a b. m a -> (a -> m b) -> m b)
     -> m (m a) -> m a

不幸的是,Djinn 使用的技术根本无法处理 rank-2 类型。如果你浮动 foralls 以便 Djinn 可以处理它,突然你得到的是 concrete 选择:

join :: (b -> m b)
     -> (m c -> (c -> m d) -> m d)
     -> m (m a) -> m a

这看起来不太可能实现!如果你告诉 Djinn 使用哪些实例化,它当然会做得更好。

join :: (b -> m b)
     -> (m (m a) -> (m a -> m a) -> m a)
     -> m (m a) -> m a

对于这一点,Djinn 会给出正确的实现。 ...但是,那是作弊。