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

Djinn实际上确实创造了一些奇迹。最初(至少对我而言)不直观的函数>>= (>>=)的类型签名为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上找到其他标准函数。
  • join(应该为join = (>>= id)或Djinn更详细的语法join a = a >>= (\x -> x))
    Djinn> join ? Monad m => m (m a) -> m a
    -- join cannot be realized.
    
  • liftM(应该为liftM f = (>>= (return . f))或Djinn更详细的语法liftM a b = b >>= (\x -> return (a x)))
    Djinn> liftM ? Monad m => (a -> b) -> m a -> m b
    -- liftM cannot be realized.
    
  • Djinn或return :: Monad m => m a -> m (m a)都无法找到基本的return :: Monad m => (a, b) -> m (a, b)
    Djinn> f ? Monad m => (a, b) -> m (a, b)
    -- f cannot be realized.
    

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

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

    最佳答案

    正确地支持类型类看起来很像支持等级2类型。比较:

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

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

    不幸的是,Djinn使用的技术根本无法处理等级2类型。如果您浮出水面以便Djinn可以处理它,那么突然得到的是具体的选择:
    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将给出正确的实现方案。 ...但是那是作弊。

    关于haskell - 为什么Djinn无法实现常见的单子(monad)函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28134149/

    10-10 16:25