最近,我偶然发现了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.
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/