我最近偶然发现了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
不幸的是,Djinn似乎无法在Monad上找到其他标准函数,尽管他们知道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
的情况,但我不知道如何使其更具体,而不是当前的手工波浪形式或者直觉是否正确。
答案 0 :(得分:10)
正确支持类型类似于支持rank-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使用的技术根本不处理rank-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将给出正确的实施。 ......但是,这是作弊。