Esta pregunta no es subjetiva. Se utiliza un verbo muy específico en el libro de referencia, y me gustaría entender cuál es la implicación de esa redacción, porque me temo que estoy malinterpretando algo.
De Learn You a Haskell , el siguiente párrafo es el tercero y último que contiene "asumimos *
".
data Barry t k p = Barry { yabba :: p, dabba :: t k }
Y ahora queremos que sea una instancia de
Functor
.Functor
quiere tipos de tipos,* -> *
peroBarry
no parece que tenga ese tipo. ¿Cuál es el tipo deBarry
? Bueno, vemos que toma tres parámetros de tipo, por lo que serásomething -> something -> something -> *
. Es seguro decir quep
es un tipo concreto y, por lo tanto, tiene una especie de*
. Parak
, suponemos*
y así, por extensión,t
tiene una especie de* -> *
. Ahora vamos a reemplazar esos tipos con lossomething
s que usamos como marcadores de posición y vemos que tiene una especie de(* -> *) -> * -> * -> *
.
¿Por qué estamos asumiendo algo? Al leer "asumimos X (es decir, suponemos que X es verdadero)" es natural para mí pensar que también deberíamos considerar el caso de que X es falso. En el caso específico del ejemplo, ¿no podría t
ser amable (* -> *) -> *
y k
amable (* -> *)
? Si este fuera el caso, lo que sea t
y k
realmente fuera, t k
seguiría siendo un tipo concreto, ¿no?
Veo que toda la línea de razonamiento se compara con el compilador, pero no creo que el compilador asuma . Si es así, me gustaría saber qué, si no es así, nuevamente me temo que me estoy perdiendo el significado del párrafo.
k :: L
para cualquier tipoL
, siempre y cuandot :: L -> *
. Sin embargo, un compilador aquí debe elegir algunos específicosL
, o recurrir a un polykind. Un polykind sería la opción más general, pero aquí elige GHCL = *
(Haskell básico no tiene polykinds, deben activarse como una extensión). Como elige algo que es bastante arbitrario, LYAH usa la palabra "asumir" (AFAICT).Respuestas:
De hecho, ¡el compilador asume! Pero puede pedir que no lo haga con la extensión PolyKinds. Puedes leer sobre esto con más detalle aquí . Con esa extensión activada, el tipo de
Barry
seráforall k. (k -> *) -> k -> * -> *
.fuente
Buen punto. El autor hace una suposición innecesaria. Quizás solo para que sea más fácil de entender en su capítulo de Type Foo, pero las personas como usted pueden cuestionar esto con razón.
Ambas
t
,k
yp
son variables de tipo. Como vemosyabba :: p
, puede vivir solo, por lo que es como una función constante, como si fuera un valor en lugar de un tipo, su firma de tipo diríaInt
oChar
, lo que sea ... lo que sea. Pero dado que es un tipo, su firma es amable*
.Sin embargo
t
escriba aquí tiene una variable de tipok
para la construcción de un tipo (dabba :: t k
)por lo que estamos seguros de que (sin assumtion aquí).t
tiene una firma misma clase* -> *
yk
tiene*
Una vez que sabemos esto ... el tipo
Barry t k p
's firma tipo es(* -> *) -> * -> * -> *
lo que significa que se necesitat
a continuación,k
y luegop
y nos daBarry
escribe.Editar Asegúrese de leer el comentario de @ luqui a continuación.
fuente
k
no está obligado a ser*
como usted afirma que es mientras deducet
. Podríamos tenerk :: * -> *
yt :: (* -> *) -> *
, por ejemplo. Agregue un campodoo :: k Int
al registro y pasará sin problemas.