2016-09-28 3 views
4

кажется обычным в зависимом от типизированного программирования для определенияПорядок аргументов типа в индексированных векторах

data Vec :: Type -> Nat -> Type where 
    Nil :: Vec a 'Z 
    Cons :: a -> Vec a n -> Vec a ('S n) 

В Haskell, однако, Functor, Applicative, Foldable, Traversable, Eq1, Ord1 и т.д., классы кажутся чтобы сделать хороший пример для опрокидывания аргументов, до Vec :: Nat -> Type -> Type.

Есть ли какая-то важная причина для обычного соглашения? Или это просто то, что люди используют на языках, не основанных на классах классов?

+0

Для чего вы стоите, вы не первый, кто наткнулся на это. [Это] (https://blog.jle.im/entry/fixed-length-vector-types-in-haskell-2015.html) сообщение (которое делает экземпляр для большинства упомянутых вами классов) также имеет 'Vec: : Nat -> Тип -> Тип'. – Alec

+0

'Тип -> Nat -> Тип' - это обычно более общий порядок, в математике (' ℝ³' и т. Д.) И курсирующих забытых языках ('std :: array '). Currying - вот что делает заказ Haskell полезным. – leftaroundabout

+0

[This] (http://stackoverflow.com/a/40252235/3072788) вид трюка с 'Bump' невозможен, если' Nat' не встречается в последней позиции. – Alec

ответ

7

Я думаю, что это не только условно, но и связано с параметрами по сравнению с индексами на некоторых языках с зависимой печатью. Например, Agda и Coq требуют, чтобы параметры приходили перед индексами в определениях типов данных. Мы бы написать

data Vec (A : Set) : Nat -> Set where ... 

в Agda, потому что мы хотим, чтобы Set аргумент, который будет рассматриваться в качестве параметра. Если бы поменять порядок аргументов и писать

data Vec : Nat -> Set -> Set where ... 

вместо этого, Set аргумент будет рассматриваться в качестве индекса. Разумеется, мы все равно будем использовать его в качестве параметра в сигнатурах конструктора, но средство проверки типа Agda пропустит информацию о том, что это параметр.

В Haskell порядок параметров не имеет значения, поэтому использование заказа, который хорошо работает с каррированием, является хорошей идеей.

В Agda, я иногда использую следующие работы вокруг, чтобы получить выделки права:

data Vec' (A : Set) : Nat -> Set 

Vec : Nat -> Set -> Set 
Vec n A = Vec' A n 

{-# DISPLAY Vec' A n = Vec n A #-} 

data Vec' A where 
    nil : Vec zero A 
    cons : {n : Nat} -> A -> Vec n A -> Vec (succ n) A 

Но я не уверен, что дополнительная нагрузка на читателях коды стоит.

+3

Только это, да. И досадно это часто. В Haskell я сначала поместил длину ... или обобщил на funxtors на индексированных множествах. – pigworker

+0

Знаете ли вы, почему * Агда ведет себя так? Стоит ли слишком дорого проверять, является ли каждый аргумент параметром или индексом (как GHC)? – dfeuer

+2

@dfeuer Я думаю, что GHC не должен генерировать связанный с этим принцип индукции индуктивным типом, но Агда должен. Выше «A» может быть выбран как параметр или индекс, и каждый выбор генерирует другой принцип индукции. Я думаю, что нет «правильного» выбора, который может сделать Agda, поэтому лучше разрешить использование решения. – chi