Zhi*_*gor 4 monads haskell arrows category-theory
我试着写下来joinArr :: ??? a => a r (a r b) -> a r b。我想出了一个使用 的解决方案app,因此将范围缩小a到ArrowApply's:
joinArr :: ArrowApply a => a r (a r b) -> a r b
joinArr g = g &&& Control.Category.id >>> app
Run Code Online (Sandbox Code Playgroud)
是否可以为箭头写下此功能?
我的猜测是否定的。
Control.Monad.join可能>>=是Monad类型类定义中的一个很好的替代品:m >>= k = join $ k <$> m.
有了joinArr :: Arrow a => a r (a r b) (a r b)我们的手,就可以写下instance Arrow a => Monad (ArrowMonad a):
m >>= k = joinArr (k <$> m)
Run Code Online (Sandbox Code Playgroud)
请注意,joinArr应该稍微调整一下才能处理包装器。如果我们说ArrowApply:
joinArr :: ArrowApply a => ArrowMonad a (ArrowMonad a b) -> ArrowMonad a b
joinArr (ArrowMonad m) = ArrowMonad $
m &&& Control.Category.id >>>
first (arr (\x -> let ArrowMonad h = x in h)) >>>
app
Run Code Online (Sandbox Code Playgroud)
instance ArrowApply a => Monad (ArrowMonad a)已经在源文件中实现了。
我认为这个论点不是最好的(如果它是对的)。
我对吗?支持(或反驳)这一点的更正式的方法是什么?
我认为你不能实现a x (a x y) -> a x yusing only的正式原因Arrow是这需要应用程序(如你所尝试)或柯里化的概念,或者在这种情况下不柯里化:
uncurry :: a x (a y z) -> a (x, y) z
Run Code Online (Sandbox Code Playgroud)
有了这个,joinArr很简单:
joinArr :: a x (a x y) -> a x y
joinArr f = dup >>> uncurry f
where dup = id &&& id
Run Code Online (Sandbox Code Playgroud)
但是如果我们不能在没有apply, curry, or 的情况下实现这个uncurry,那意味着它a必须是一个笛卡尔闭范畴(CCC),因为我们需要一些“指数”或高阶箭头的概念,它ArrowApply给了我们,但Arrow只给了我们一个笛卡尔类别。(并且我相信ArrowApply相当于Monad因为Monad是CCC 中的强单子。)
你能得到的最接近的Arrow是 an Applicative,正如你在 的定义中看到的那样instance (Arrow a) => Applicative (ArrowMonad a),它恰好与join在Readermonad中的权力相同(从那里开始join = (<*> id)),但不是更强的 monadic join:
joinArr' :: a x (x -> y) -> a x y
joinArr' f = (f &&& id) >>> arr (uncurry ($))
Run Code Online (Sandbox Code Playgroud)
请注意,这里没有a x (a x y)使用高阶箭头,我们只是重用了(->)类型。