Is it possible to write join down for Arrows, not ArrowApply?

前端 未结 1 1712
梦谈多话
梦谈多话 2021-01-19 04:23

I tried writing down joinArr :: ??? a => a r (a r b) -> a r b. I came up with a solution which uses app, therefore narrowing the a

1条回答
  •  隐瞒了意图╮
    2021-01-19 04:35

    I think the formal reason that you can’t implement a x (a x y) -> a x y using only Arrow is that this requires a notion of either application (as you tried) or currying, or rather uncurrying in this case:

    uncurry :: a x (a y z) -> a (x, y) z
    

    With that, joinArr is simply:

    joinArr :: a x (a x y) -> a x y
    joinArr f = dup >>> uncurry f
      where dup = id &&& id
    

    But if we can’t implement this without apply, curry, or uncurry, that means that a must be a Cartesian closed category (CCC) because we need some notion of “exponential” or higher-order arrow, which ArrowApply gives us, but Arrow only gives us a Cartesian category. (And I believe ArrowApply is equivalent to Monad because Monad is a strong monad in a CCC.)

    The closest you can get with only Arrow is an Applicative, as you saw in the definition of instance (Arrow a) => Applicative (ArrowMonad a), which happens to be equivalent in power to join in the Reader monad (since there join = (<*> id)), but not the stronger monadic join:

    joinArr' :: a x (x -> y) -> a x y
    joinArr' f = (f &&& id) >>> arr (uncurry ($))
    

    Note that instead of a higher-order arrow here, a x (a x y), we just reuse the (->) type.

    0 讨论(0)
提交回复
热议问题