好吧,我正在研究Haskell Monads。当我阅读Wikibook Category theory文章时,我发现monad态射的签名看起来很像逻辑中的重言式,但你需要将M a
转换为~~A
,这里~
是逻辑否定。
return :: a -> M a -- Map to tautology A => ~~A, double negation introduction
(>>=) :: M a -> (a -> M b) -> M b -- Map to tautology ~~A => (A => ~~B) => ~~B
其他操作也是重言式:
fmap :: (a -> b) -> M a -> M b -- Map to (A => B) -> (~~A => ~~B)
join :: M (M a) -> M a -- Map to ~~(~~A) => ~~A
还可以理解,根据正常函数语言的Curry-Howard对应关系是直观逻辑而非经典逻辑的事实,我们不能指望像~~A => A
这样的重言式可以有对应关系。 / p>
但我正在考虑别的事情。为什么Monad只能与双重否定相关?单一否定的对应关系是什么?这引出了以下类定义:
class Nomad n where
rfmap :: (a -> b) -> n b -> n a
dneg :: a -> n (n a)
return :: Nomad n => a -> n (n a)
return = dneg
(>>=) :: Nomad n => n (n a) -> (a -> n (n b)) -> n (n b)
x >>= f = rfmap dneg $ rfmap (rfmap f) x
这里我定义了一个名为“Nomad”的概念,它支持两种操作(都与直觉逻辑中的逻辑公理相关)。请注意,名称“rfmap”表示其签名与仿函数fmap
类似,但a
和b
的顺序在结果中相反。现在我可以用它们重新定义Monad操作,将M a
替换为n (n a)
。
现在让我们回到问题部分。 Monad是一个来自范畴理论的概念,这似乎意味着我的“Nomad”也是一个范畴理论概念。那是什么?它有用吗?这个主题是否有任何论文或研究成果?
答案 0 :(得分:19)
双重否定是特定的 monad
data Void --no constructor because it is uninhabited
newtype DN a = DN {runDN :: (a -> Void) -> Void}
instance Monad DN where
return x = DN $ \f -> f x
m >>= k = DN $ \c -> runDN m (\a -> runDN (k a) c))
实际上,这是更一般的monad
的一个例子type DN = Cont Void
newtype Cont r a = Cont {runCont :: (a -> r) -> r}
这是继续传球的单子。
像“monad”这样的概念不是仅仅通过签名来定义,而是通过某些定律来定义。所以,这是一个问题,你的建筑法律应该是什么?
(a -> b) -> f b -> f a
是类别理论众所周知的方法的签名,逆变函子。它遵循与仿函数基本相同的规律(保留(共同)构成和身份)。实际上,逆变函子恰好是对立类的一个算符。由于我们对应该是endo-functors的“haskell仿函数”感兴趣,我们可以看到“haskell逆变仿函数”是一个仿函数Hask -> Hask_Op
。
另一方面,
怎么样?a -> f (f a)
这应该是什么法律?我有个建议。在类别理论中,可以在Functors之间进行映射。鉴于F, G
中的两个仿函数,从C
类到D
类,从F
到G
的自然转换是一种态射在D
forall a. F a -> G a
遵守某些连贯性法律。您可以使用自然变换做很多事情,包括使用它们来定义“仿函数类别”。但是,经典的笑话(由于Mac Lane)是因为发明类别是为了讨论仿函数,发明仿函数是为了谈论自然变换,而自然变换被发明来讨论 adjunctions 。
如果存在两个自然变换,仿函数F : D -> C
和仿函数G : C -> D
形成从C
到D
的附属物
unit : Id -> G . F
counit : F . G -> Id
这种附属概念是理解monad的常用方法。每个附属物都以完全自然的方式产生一个单子。也就是说,由于这两个仿函数的组合是一个endofunctor,并且你有类似返回(单位)的东西,你只需要连接。但这很容易,加入只是一个函数G . F . G . F -> G . F
,你可以通过使用“在中间”的方式获得。
那么,有了这一切,你在寻找什么?好吧
dneg :: a -> n (n a)
看起来与逆变函子的自身的unit
完全相同。因此,你的Nomad
类型很可能(当然,如果你使用它来构造一个monad是正确的)与“自伴的逆变函子”完全相同。搜索自伴函子会让你回到Double-negation和Continuation传递......这就是我们开始的地方!
编辑:几乎可以肯定,上面的一些箭头是倒退的。不过,基本的想法是正确的。您可以使用下面的引文自行解决:
关于范畴理论的最佳书籍可能是,
在线视频讲座
许多论文探讨了连续monad的附加角度,例如
搜索词“self adjoint”,“continuation”和“monad”都很好。此外,一些博客撰写了关于这些问题的文章。如果你谷歌“monad来自哪里”,你可以从n类咖啡馆获得有用的结果,如this one,或者从sigfpe获得this one。也是Sjoerd Vissche对Comonad读者的link。
答案 1 :(得分:8)
那将是一个自伴的逆变函子。 rfmap
提供逆变函子部分,dneg
是附加函数的单位和对象。
Op r
是一个示例,它创建了continuation monad。有关代码,请参阅http://hackage.haskell.org/package/adjunctions中的逆变模块。
你应该阅读http://comonad.com/reader/2011/monads-from-comonads/,这是相关且非常有趣的。