是否可以为 Arrows 而不是 ArrowApply 写下连接?

Zhi*_*gor 4 monads haskell arrows category-theory

我试着写下来joinArr :: ??? a => a r (a r b) -> a r b。我想出了一个使用 的解决方案app,因此将范围缩小aArrowApply'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)已经在源文件中实现了。

我认为这个论点不是最好的(如果它是对的)。

我对吗?支持(或反驳)这一点的更正式的方法是什么?

Jon*_*rdy 6

我认为你不能实现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因为MonadCCC 中的强单子。)

你能得到的最接近的Arrow是 an Applicative,正如你在 的定义中看到的那样instance (Arrow a) => Applicative (ArrowMonad a),它恰好joinReadermonad中的权力相同(从那里开始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)使用高阶箭头,我们只是重用了(->)类型。