Este es un ejemplo mínimo tomado de Reflection-0.5.Haskell: ¿Por qué este tipo de verificación?
{-# LANGUAGE Rank2Types, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}
{-# OPTIONS_GHC -fno-cse -fno-full-laziness -fno-float-in #-}
import Control.Applicative
import Data.Proxy
newtype Zero = Zero Zero deriving (Show)
class ReifiesNum s where
reflectNum :: Num a => proxy s -> a
instance ReifiesNum Zero where
reflectNum = pure 0
En GHCi, me sale el siguiente:
>:t Zero
Zero :: Zero -> Zero
Esto tiene sentido: lo que estoy pidiendo el tipo de constructor que tiene un cero y devuelve un cero.
>:t reflectNum
reflectNum :: (ReifiesNum s, Num a) => proxy s -> a
Tiene sentido que podría escribir algo así como
>let x = Just (undefined::Zero)
>reflectNum x
porque el tipo Justo cero coincide con las variables de tipo de proxy 's'.
Por último, la parte confusa:
>:t (reflectNum Zero)
(reflectNum Zero) :: Num a => a
No entiendo cómo el tipo del constructor Cero Cero :: -> Cero aparentemente coincide con las variables de tipo de proxy 's', pero al parecer lo hace debido a que la tipo de (reflectNum Zero) es solo 'a'.
Agradecería ayuda para entender este ejemplo, y los enlaces a los conceptos relevantes serían muy apreciados.
Gracias
¿Por qué "(->) Zero" es un tipo válido? No puedo imaginar cómo podría escribir algo como "> dejar x = [algo] :: ((->) cero"). Espero que tenga sentido. ¡Gracias por la respuesta! – crockeea
@Eric '(->) Zero' no es un tipo válido, es un * constructor de tipo *, que debe aplicarse a otro tipo para formar un tipo concreto. Lo mismo es cierto de 'Maybe'; no hay valores de tipo 'Maybe', pero hay valores de tipo' Maybe Int', 'Maybe [Double]', 'Maybe (Maybe (Maybe Char))', etc. Del mismo modo, no hay valores de tipo ' (->) Zero', pero hay valores de tipo '(->) Zero Zero', es decir,' Zero -> Zero'. – Ben
Gracias Ben. Me faltaba la notación infijo vs prefijo, ¡pero está claro ahora! – crockeea