为什么 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 上找到其他标准函数。
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
视为 "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 会给出正确的实现。 ...但是,那是作弊。
我最近偶然发现了 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 上找到其他标准函数。
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
视为 "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 会给出正确的实现。 ...但是,那是作弊。