Подтвердить что ты не робот

Haskell Arrow-Class в Агда и → в Агда

У меня есть два тесно связанных вопроса:

Во-первых, как класс Haskell Arrow может быть смоделирован/представлен в 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')

(следующая Сообщение в блоге гласит, что это должно быть возможно...)

Во-вторых, в Haskell (->) является первоклассным гражданином и просто еще одним типом более высокого порядка, и его просто определить (->) как один экземпляр класса Arrow. Но как это происходит в Агда? Я мог ошибаться, но я чувствую, что Agdas -> является более неотъемлемой частью Agda, чем Haskell ->. Таким образом, Agdas -> можно рассматривать как тип более высокого порядка, т.е. Функцию типа, дающую Set, которая может быть сделана экземпляром Arrow?

4b9b3361

Ответ 1

Типовые классы обычно кодируются как записи в Agda, поэтому вы можете кодировать класс Arrow как-то вроде этого:

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')

Пока вы не можете напрямую ссылаться на тип функции (что-то вроде _→_ не является допустимым синтаксисом), вы можете написать свое собственное имя для него, которое вы можете использовать при записи экземпляра:

_=>_ : 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)
  }

Ответ 2

В то время как ответ hammar является правильным портом кода Haskell, определение _=>_ слишком ограничено по сравнению с ->, поскольку оно не поддерживает зависимые функции. При адаптации кода из Haskell это стандартное необходимое изменение, если вы хотите применить свои абстракции к функциям, которые вы можете написать в Agda.

Кроме того, по обычному стандарту стандартной библиотеки этот класс будет называться RawArrow, потому что для его реализации вам не нужно предоставлять доказательства того, что ваш экземпляр удовлетворяет законам стрелок; см. RawFunctor и RawMonad для других примеров (примечание: определения Functor и Monad нигде не видны в стандартной библиотеке, начиная с версии 0.7).

Здесь более мощный вариант, который я написал и протестировал с помощью Agda 2.3.2 и стандартной библиотеки 0.7 (также должен работать на версии 0.6). Обратите внимание, что я только изменил объявление типа параметра RawArrow и _=>_, остальное не изменилось. При создании fnArrow, однако, не все объявления альтернативного типа работают по-прежнему.

Предупреждение: я только проверял, что код typechecks и that = > можно использовать разумно, я не проверял, используют ли примеры RawArrow typecheck.

module RawArrow where

open import Data.Product --actually needed by RawArrow
open import Data.Fin     --only for examples
open import Data.Nat     --ditto

record RawArrow (A : (S : Set) → (T : {s : S} → 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')

_=>_ : (S : Set) → (T : {s : S} → Set) → Set
A => B = (a : A) -> B {a}

test1 : Set
test1 = ℕ => ℕ
-- With → we can also write:
test2 : Set
test2 = (n : ℕ) → Fin n
-- But also with =>, though it more cumbersome:
test3 : Set
test3 = ℕ => (λ {n : ℕ} → Fin n)
--Note that since _=>_ uses Set instead of being level-polymorphic, it still
--somewhat limited. But I won't go the full way.

--fnRawArrow : RawArrow _=>_
-- Alternatively:
fnRawArrow : RawArrow (λ A B → (a : A) → B {a})

fnRawArrow = 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)
  }