I have two closely related questions:
First, how can the Haskell's Arrow class be modeled / represented in Agda?
class Arrow a where
arr :: (b -> c) -> a b c
(>>>) :: a b c -> a c d -> a b d
first :: a b c -> a (b,d) (c,d)
second :: a b c -> a (d,b) (d,c)
(***) :: a b c -> a b' c' -> a (b,b') (c,c')
(&&&) :: a b c -> a b c' -> a b (c,c')
(the following Blog Post states that it should be possible...)
Second, in Haskell, the (->) is a first-class citizen and just another higher-order type and its straightforward to define (->) as one instance of the Arrow class. But how is that in Agda? I could be wrong, but I feel, that Agdas -> is a more integral part of Agda, than Haskell's -> is. So, can Agdas -> be seen as a higher-order type, i.e. a type function yielding Set which can be made an instance of Arrow?
Type classes are usually encoded as records in Agda, so you can encode the Arrow class as something like this:
open import Data.Product -- for tuples
record Arrow (A : Set → Set → Set) : Set₁ where
field
arr : ∀ {B C} → (B → C) → A B C
_>>>_ : ∀ {B C D} → A B C → A C D → A B D
first : ∀ {B C D} → A B C → A (B × D) (C × D)
second : ∀ {B C D} → A B C → A (D × B) (D × C)
_***_ : ∀ {B C B' C'} → A B C → A B' C' → A (B × B') (C × C')
_&&&_ : ∀ {B C C'} → A B C → A B C' → A B (C × C')
While you can't refer to the function type directly (something like _→_ is not valid syntax), you can write your own name for it, which you can then use when writing an instance:
_=>_ : Set → Set → Set
A => B = A → B
fnArrow : Arrow _=>_ -- Alternatively: Arrow (λ A B → (A → B)) or even Arrow _
fnArrow = record
{ arr = λ f → f
; _>>>_ = λ g f x → f (g x)
; first = λ { f (x , y) → (f x , y) }
; second = λ { f (x , y) → (x , f y) }
; _***_ = λ { f g (x , y) → (f x , g y) }
; _&&&_ = λ f g x → (f x , g x)
}