2017-02-09 4 views
2

Допустим, мы имеем:Почему haskell вынуждает всегда вводить общие типы?

data Data a b c = Build (a,b,c) deriving Show 

foo :: Data a b c -> Data a b c 
foo d = d 

main = print $ foo $ Build (1, 1, "a") 

Есть ли способ избежать написания a b c для каждого использования типа данных?

Использование типа, что-то вроде:

foo :: Data -> Data 
foo d = d 
+3

На самом деле вы не * имеете *, чтобы писать сигнатуры типов вообще. Если вы их опустите, Haskell выведет их для вас. –

+0

@WillemVanOnsem, я знаю об этом, скажем, кроме этого. Будет ли редактировать – Netwave

ответ

11

Да, конечно:

foo :: d ~ Data a b c => d -> d 
+1

ok, псевдоним типа? – Netwave

+0

@ DanielSanchez Нет, это [ограничение равенства] (https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/equality-constraints.html). В основном это говорит о том, что тип 'd' должен быть равен 'Data a b c', но у вас могут быть более сложные ограничения, такие как' A a b c ~ B d e f'. Haskell * does * имеют синонимы типов, но вам либо нужно сделать их ранг 2, либо добавить параметры. – Bakuriu

+0

@ Даниэль Вагнер, спасибо, что использую это – Netwave

0

Поскольку Data не тип, а конструктор типа. Если вы предпочитаете функцию, которая принимает 3 типа и возвращает новый тип. Конструкторы типов могут также и другие типы конструкторов типов, как, например аргумент

data D d a= D (d a a a) 

Затем я могу использовать свой Data (без аргументов) D Data a ...

Псевдонимы
8
data Data a b c = Build (a,b,c) deriving Show 
type D a t a' = Data a t a' 

foo :: D a t a' -> D a t a' 
foo d = d 

весело, но это не следует рассматривать как серьезный ответ.

Edit: серьезная версия, если вы знаете, общий тип мономорфический тогда псевдонимы становятся полезными:

type AppData = Data AppState AppValue AppResult 
foo :: AppData -> AppData 
... 
+0

Отличный ответ. –

+0

Это очень изобретательная, отличная работа! – AJFarmar

3

Вы можете обернуть полиморфный тип в type синонима.

{-# LANGUAGE RankNTypes #-} 
{-# LANGUAGE TypeOperators #-} 

type d ~> d' = forall a b c. d a b c -> d' a b c 

foo :: Data ~> Data 
foo d = d 

Возможно, проще просто написать переменные типа.

+0

Я не совсем понимаю это, не могли бы вы принести мне свет из веб-ссылки или что-то вроде этого? спасибо – Netwave

+1

@ DanielSanchez: Вкратце, когда у вас есть переменные типа в сигнатуре, они неявно имеют * квантификаторы *, которые определяют их область видимости, поэтому 'foo :: Data a b c -> Data a b c' неявно' forall a b c. Данные a b c -> Данные a b c'. Тип 'Data ~> Data' расширяется до одного и того же,' forall a b c. Данные a b c -> Данные a b c', заменив 'd' и' d''на' Data'. –

+0

@ JonPurdy Понял сейчас, спасибо !! – Netwave

Смежные вопросы