2016-12-10 57 views
8

Wpadłem w dziwną sytuację w GHC 8.0.1 z dobrymi indeksami (?) GADTs, w których wprowadzenie kombinezonów w sygnaturach typu i rodzaju powoduje różne sprawdzanie typów zachowania."Rodzaj" zdezorientowany na temat all-in w GADTs indeksowanych

Rozważmy następujące typy danych:

{-# LANGUAGE TypeInType, GADTs, ExplicitForAll #-} 
-- Same thing happens when we replace ExplicitForAll with ScopedTypeVariables 

import Data.Kind 

data F (k :: * -> *) where 

data G :: F k -> * where 
    G :: G x 

Ten typ danych kompiluje dobrze. Jeśli jednak chcemy określić rodzaj x w konstruktorze G, otrzymamy błąd typu.

data H :: F k -> * where 
    H :: forall k' (x :: F k'). H x 

Komunikat o błędzie jest

• Kind variable ‘k’ is implicitly bound in datatype 
    ‘H’, but does not appear as the kind of any 
    of its type variables. Perhaps you meant 
    to bind it (with TypeInType) explicitly somewhere? 
• In the data declaration for ‘H’ 

Jeśli dodamy forall do podpisu naturze (z lub bez forall w konstruktorze), nie ma błędu.

data I :: forall k. F k -> * where 
    I :: I x 

data J :: forall k. F k -> * where 
    J :: forall k' (x :: F k'). J x 

Co się dzieje?

+6

naprawdę doskonała gra słów. A + – rampion

+0

Wygląda na to, że pierwsza deklaruje "F k", która ma być ustalona dla całej deklaracji, podczas gdy druga pozwala na użycie 'H' w swojej własnej deklaracji w różnych rodzajach. To znaczy. umożliwia polikindową rekursję. Może być podobny do rozróżnienia "parametry vs wskaźniki" w typach indukcyjnych (jak w Agdzie/Coq). – chi

+3

Wygląda na to, że może to być (ostatnio naprawiony) błąd kompilatora. Mogę zduplikować twój komunikat o błędzie za pomocą "ghc-8.0.1", ale kompiluje się dobrze z "ghc-8.0.1.20161117", najnowszą wersją, którą "stack" postanowił zainstalować dla mnie (i która wydaje się być kandydatem do wydania na 8.0 .2). –

Odpowiedz

3

Autor tutaj: TypeInType. K. A. Buhr robi to dokładnie powyżej; to tylko błąd. Naprawiono go w HEAD.

Dla zbyt ciekawy: ten komunikat ma na celu wyeliminowanie definicje jak

data J = forall (a :: k). MkJ (Proxy a) 

gdzie

data Proxy (a :: k) = Proxy 

mogą być importowane z Data.Proxy. Deklarując typ danych w składni w stylu Haskell98, dowolne zmienne z konieczności ilościowo muszą być jawnie wprowadzone w zakres przy pomocy forall. Ale k nigdy nie zostaje wyraźnie zawarty w zakresie; jest używany tylko w rodzaju a. Oznacza to, że wartość parametrupowinna być określona uniwersalnie (innymi słowy, powinna być niewidoczna dla parametru J, taka jak parametr k dla Proxy) ... ale wtedy, gdy piszemy J, nie ma możliwości określenia, która wartość powinna być . , więc zawsze będzie niejednoznaczna. (W przeciwieństwie do tego, możemy odkryć Wybór parametru k do Proxy patrząc na rodzaj a „s.)

Ta definicja J jest niedozwolone w 8.0.1 i HEAD.