tutorial online funciones empresa descargar constructora company haskell

online - haskell pdf



¿Por qué el operador en dólares($) es tan complejo en GHC 8.0.1? (1)

Antes de la versión 8.0, había un caso especial en el buscador de tipos para hacer que funcionaran las aplicaciones de $ a tipos diferentes. Esto también significaba que no podía definir sus propias funciones que podrían funcionar con tipos elevados y sin elevar. Ahora que este llamado Levity Polymorphsim (''levidad'' se refiere a ''el grado en que algo se levanta'' - o ''lifting-ness'', debido a los tipos ''desatado'' y ''levantado'') está integrado en el comprobador de tipos, esto es posible:

import GHC.Exts (TYPE, RuntimeRep(..)) import Data.Kind (type (*)) ap :: forall (a :: *) (b :: *) . (a -> b) -> (a -> b) ap f x = f x ap_LP :: forall (a :: *) (b :: TYPE r) . (a -> b) -> (a -> b) ap_LP f x = f x

y, de hecho, la función $ ahora se define de forma idéntica a ap_LP , sin que se necesite un caso especial en el buscador de tipos para hacer que $ funcione con funciones que devuelven tipos desentendidos (todavía hay un caso especial en el buscador de errores para hacer una aplicación polimórfica, es decir, runST $ ... .trabajo, pero esto no está relacionado con el polimorfismo de la levedad). Esta es esencialmente la razón de la complejidad agregada: ahora hay menos ''hacks'' en el sistema de tipos, y los usuarios de GHC pueden aprovechar el polimorfismo de levidad simplemente al asignar a una función el tipo apropiado (tenga en cuenta que los tipos polimórficos de levidad nunca se deducen , Por lo que yo puedo decir). Antes del polimorfismo de la ligereza, si deseaba escribir una función polimórfica que pudiera funcionar en los tipos levantado y sin elevar, estaba obligado a escribir dos copias idénticas de la función con diferentes tipos de firmas.

El nuevo tipo difiere del anterior en que el nuevo tipo es estrictamente más general que el anterior:

-- ok ap'' :: forall (a :: *) (b :: *) . (a -> b) -> (a -> b) ap'' = ap_LP -- type error: -- * Couldn''t match a lifted type with an unlifted type ap_LP'' :: forall (a :: *) (b :: TYPE r) . (a -> b) -> (a -> b) ap_LP'' = ap

En otras palabras, cada b que "se ajuste" a la firma anterior debe (por definición) adaptarse a la nueva firma de tipo (¡y por lo tanto este cambio es perfectamente compatible con versiones anteriores!).

También tenga en cuenta que lo siguiente no es posible:

ap'''' :: forall (a :: TYPE r) (b :: *) . (a -> b) -> (a -> b) ap'''' f x = f x

El error producido es

A representation-polymorphic type is not allowed here: Type: a Kind: TYPE r In the type of binder `x''

y SPJ explica la razón de la restricción here :

Es absolutamente correcto que el segundo argumento de ($) no debe tener un tipo sin caja. Debido a que el código para ($) debe mover ese argumento (pasar a la función), debe conocer su ancho, puntería, etc.

Pero en realidad estaría bien si el resultado de la llamada (f $ x) no estuviera en la caja, porque el código para ($) no se mete con el resultado; es sólo una llamada de cola f.

Esto quiere decir que no todos los tipos polimórficos de levidad tienen un habitante válido, y esto se relaciona con la distinción operacional entre los tipos sin caja y con caja, que solo pueden tratarse de manera uniforme en ciertos casos, y el tipógrafo se asegura de ello.

Prelude> :i ($) ($) :: forall (r :: GHC.Types.RuntimeRep) a (b :: TYPE r). (a -> b) -> a -> b -- Defined in ‘GHC.Base’ infixr 0 $

¿En qué se diferencia de (a -> b) -> a -> b ? ¿Hay alguna b que no se ajuste a la nueva firma de tipo?