Jakie jest założenie przyjęte w „Learn You a Haskell” podczas dedukcji tego rodzaju?

18

To pytanie nie jest subiektywne. Bardzo konkretny czasownik jest używany w książce, do której się odwołuje, i chciałbym zrozumieć, jakie są implikacje tego sformułowania, ponieważ obawiam się, że coś źle zrozumiałem.

W Learn You a Haskell poniższy akapit jest trzecim i ostatnim, który zawiera „zakładamy *”.

data Barry t k p = Barry { yabba :: p, dabba :: t k }  

A teraz chcemy zrobić z tego przykład Functor. Functorchce rodzajów, * -> *ale Barrynie wygląda na to, że ma tego rodzaju. Jakiego rodzaju Barry? Widzimy, że wymaga trzech parametrów typu, więc tak będzie something -> something -> something -> *. Można śmiało powiedzieć, że pjest to konkretny typ, a zatem ma swego rodzaju *. Dla kzakładamy, *a więc co za tym idzie, tma niby* -> * . Teraz po prostu zamieńmy te rodzaje na te something, których używaliśmy jako symbole zastępcze i widzimy, że ma coś w rodzaju (* -> *) -> * -> * -> *.

Dlaczego w ogóle coś zakładamy? Po przeczytaniu „zakładamy, że X (tzn. Zakładamy, że X jest prawdą)” jest dla mnie naturalne, że powinniśmy również rozważyć przypadek, w którym X jest fałszywy. Czy w konkretnym przypadku tego przykładu nie może tbyć miły (* -> *) -> *i kmiły (* -> *)? Jeśli tak było, cokolwiek ti kfaktycznie tak było,t k nadal będzie to rodzaj betonu, nie?

Widzę, że cała linia rozumowania jest następnie porównywana z kompilatorem, ale nie sądzę, że kompilator zakłada . Jeśli tak, chciałbym wiedzieć, a jeśli nie, to obawiam się, że nie rozumiem znaczenia akapitu.

Enrico Maria De Angelis
źródło
4
Masz rację. Rzeczywiście, możemy mieć k :: Lna każdy rodzaj L, o ile t :: L -> *. Kompilator tutaj musi jednak wybrać jakiś konkretny Llub uciekać się do polikinda. Polykind byłby najbardziej ogólną opcją, ale tutaj GHC wybiera L = *(podstawowy Haskell nie ma polikindów, należy je włączyć jako rozszerzenie). Ponieważ wybiera coś, co jest raczej arbitralne, LYAH używa słowa „zakładać” (AFAICT).
chi
1
Ok, może kompilator zakłada , że zdziwiłby mnie przynajmniej mniej niż zakładamy , albo wcale.
Enrico Maria De Angelis,

Odpowiedzi:

19

W rzeczywistości kompilator zakłada! Ale możesz tego poprosić o rozszerzenie PolyKinds. Możesz przeczytać o tym bardziej szczegółowo tutaj . Po włączeniu tego rozszerzenia taki Barrybędzie forall k. (k -> *) -> k -> * -> *.

Daniel Wagner
źródło
-1

Słuszna uwaga. Autor dokonuje niepotrzebnego założenia. Być może po to, aby ułatwić zrozumienie w jego rozdziale Type Foo, ale ludzie tacy jak ty mogą słusznie to kwestionować.

Obaj t, ki psą zmiennymi typu. Jak widzimy yabba :: p, może żyć sam, więc jest jak stała funkcja, tak jakby to była wartość zamiast typu, jego podpis typu powiedziałby Intlub Char, cokolwiek ... jak to nazwiesz. Ale ponieważ jest to typ, jest to miły podpis* .

Jednak ttutaj typ pobiera zmienną typu, kaby skonstruować typ ( dabba :: t k), więc jesteśmy pewni, że (tutaj nie ma tutaj żadnego przypuszczenia) tma taką podobną sygnaturę jak * -> *i kma* .

Kiedy się o tym dowiemy ... Barry t k pmiły podpis (* -> *) -> * -> * -> *tego typu oznacza, że ​​trzeba go od tczasu kdo czasu ppodać i podać Barry.

Edytuj Pamiętaj, aby przeczytać komentarz @ luqui poniżej.

Redu
źródło
7
knie jest *tak, jak się twierdzi, podczas dedukcji t. Moglibyśmy k :: * -> *i t :: (* -> *) -> *na przykład. Dodaj pole doo :: k Intdo rekordu, a przejdzie ono bez problemu.
luqui,
@luqui .. Tak, masz rację ... Nie usunę tej odpowiedzi, ponieważ twój komentarz jest naprawdę wart.
Redu,