我有两个密切相关的问题:
首先,如何在Agda中对Haskell的Arrow类进行建模/表示?
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')(下面的Blog Post声明这应该是可能的…)
其次,在Haskell中,(->)是一等公民,只是另一个更高级的类型,它直接将(->)定义为Arrow类的一个实例。但这在Agda中是如何实现的呢?我可能错了,但我觉得,与Haskell的->相比,Agdas ->是Agda更完整的一部分。那么,Agdas ->是否可以被视为高阶类型,即产生Set的类型函数,该类型函数可以成为Agdas的实例
发布于 2012-10-29 04:41:33
类型类通常被编码为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)
}发布于 2013-01-31 05:41:44
虽然哈马尔的回答是哈斯克尔代码的正确移植,但与->相比,_=>_的定义太有限了,因为它不支持依赖函数。当从Haskell改编代码时,如果你想将你的抽象应用到你可以用Agda编写的函数上,这是一个标准的必要的改变。
此外,根据标准库的通常约定,这个类型类将被称为RawArrow,因为要实现它,您不需要提供实例满足箭头定律的证明;有关其他示例,请参阅RawFunctor和RawMonad (注意:从0.7版开始,标准库中看不到函数器和Monad的定义)。
这是一个更强大的变体,我用Agda 2.3.2和0.7标准库编写并测试了它(应该也可以在0.6版本上工作)。请注意,我只更改了RawArrow的参数和_=>_的类型声明,其余的没有改变。但是,在创建fnArrow时,并不是所有的替代类型声明都能像以前一样工作。
警告:我只检查了代码类型检查和=>是否可以合理使用,我没有检查示例是否使用RawArrow类型检查。
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's more cumbersome:
test3 : Set
test3 = ℕ => (λ {n : ℕ} → Fin n)
--Note that since _=>_ uses Set instead of being level-polymorphic, it's 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)
}https://stackoverflow.com/questions/13112642
复制相似问题