我试图构造类型的函数:提升高阶函数在Haskell
liftSumthing :: ((a -> m b) -> m b) -> (a -> t m b) -> t m b
其中t
是一个单子转换。具体而言,我有兴趣这样做:
liftSumthingIO :: MonadIO m => ((a -> IO b) -> IO b) -> (a -> m b) -> m b
我摆弄了一些哈斯克尔魔法库,但无济于事。我如何获得它 是正确的,或者有一个我找不到的现成解决方案?
我试图构造类型的函数:提升高阶函数在Haskell
liftSumthing :: ((a -> m b) -> m b) -> (a -> t m b) -> t m b
其中t
是一个单子转换。具体而言,我有兴趣这样做:
liftSumthingIO :: MonadIO m => ((a -> IO b) -> IO b) -> (a -> m b) -> m b
我摆弄了一些哈斯克尔魔法库,但无济于事。我如何获得它 是正确的,或者有一个我找不到的现成解决方案?
由于IO
类型处于负值,因此无法对所有MonadIO
实例进行一般化处理。关于hackage,有一些库针对特定实例执行此操作(monad-control,),但是他们是否在语义上听起来有些争议,尤其是关于它们如何处理异常和类似奇怪的事情。
编辑:有些人似乎对正面/负面的立场区分感兴趣。实际上,没有什么可说的了(你可能已经听说过了,但是以不同的名字)。术语来自分类的世界。
亚型背后的直觉是,“a
是b
一个亚型(我会写a <= b
)当a
可以在任何地方使用b
有望代替”。在很多情况下确定子类型是很直接的;对于产品,(a1, a2) <= (b1, b2)
,例如a1 <= b1
和a2 <= b2
,这是一个非常简单的规则。但是有一些棘手的案例。例如,我们应该什么时候决定a1 -> a2 <= b1 -> b2
?
那么,我们有一个功能f :: a1 -> a2
和一个预期功能类型为b1 -> b2
的上下文。所以上下文将使用f
的返回值,就好像它是一个b2
,因此我们必须要求a2 <= b2
。棘手的是,上下文将提供f
与b1
,即使f
打算使用它,就好像它是一个a1
。因此,我们必须要求b1 <= a1
--这与您可能猜到的相反!我们说a2
和b2
是“协变”,或发生在“正面位置”,并且a1
和b1
是“逆变”,或发生在“负面位置”。
(快速预留:为什么“积极”和“消极”它是由乘法动机考虑以下两种类型:
f1 :: ((a1 -> b1) -> c1) -> (d1 -> e1)
f2 :: ((a2 -> b2) -> c2) -> (d2 -> e2)
时候应该f1
的类型是f2
的子类型的类型吗?陈述这些事实(练习:检查这个使用上述规则):
e1 <= e2
d2 <= d1
c2 <= c1
。b1 <= b2
。a2 <= a1
。e1
处于d1 -> e1
正位置,其又在的f1
类型的正位置;此外,e1
总体上处于f1
类型的正面位置(因为它是协变的,根据上述事实)。它在整个学期中的位置是它在每个子项中的位置的结果:positive * positive = positive。类似地,d1
在d1 -> e1
中处于负位置,这在整个类型中处于积极的位置。负值*正值=负值,并且d
变量确实是逆变。 b1
在类型a1 -> b1
中处于正位置,在(a1 -> b1) -> c1
中处于负位置,在整个类型中处于负位置。正面*负面*负面=正面,而且是协变的。你的想法)
现在,让我们来看看MonadIO
类:
class Monad m => MonadIO m where
liftIO :: IO a -> m a
我们可以认为这是子类型的显式声明:我们都给人一种方法,使IO a
是一个亚型m a
部分混凝土m
。马上我们知道我们可以用IO
构造函数取正值,并将它们变成m
s。但仅此而已:我们无法将负面的IO
构造函数转换为m
- 我们需要一个更有趣的类。
“由于”IO“类型处于负面状态“ - 你能详细说明这意味着什么以及它为什么重要吗? – 2012-02-11 21:36:40
@丹伯顿我已经写了一些关于它的文章 – 2012-02-12 01:04:59
这当然有帮助,我认为monad-control可以让我做足够的修补。在这种情况下,没有看到从“ma”到“tma”的上下文变化会如何破坏任何东西。由于缺少其他答案,我将其设置为接受。 – zeus 2012-02-16 21:37:36
嘎!为什么所有的Haskell问题都这么难?这里没有简单的一点:-( – drozzy 2012-02-11 20:35:12
@drozzy:这个标签实际上[每个答案的平均数最高的一个] [http://data.stackexchange.com/stackoverflow/query/61353/tags-with-highest-average因为尽管它们可能并不总是那么容易,但人们确实因为努力而获得奖励。 – hammar 2012-02-12 00:02:24