2010-07-30 25 views
7

¿Es posible utilizar sinónimos de tipo como argumentos del constructor de tipo de transformadores de mónada? En particular, si hay un sinónimo de tipo unario para un transformador de mónada aplicado, ¿podría usarse como un tipo de la mónada subyacente en otro transformador de mónada?Uso de sinónimos de tipo en transformadores de mónada

Por lo que veo tipo sinónimos no se aceptan como constructores de tipo de primera clase, véase el ejemplo y mensajes de error siguientes:

-- Using type synonym of a monad transformer in another monad transformer. 

import Control.Monad.Reader 

-- inner transformer 
type A a = ReaderT Int IO a 

-- type B a = ReaderT String A a 
{- Error: 
readert2.hs:8:0: 
    Type synonym `A' should have 1 argument, but has been given 0 
    In the type synonym declaration for `B' 
-} 

-- type B a = ReaderT String (A a) a 
{- Error: 
readert2.hs:15:27: 
    Kind mis-match 
    The second argument of `ReaderT' should have kind `* -> *', 
    but `A a' has kind `*' 
    In the type `ReaderT String (A a) a' 
    In the type synonym declaration for `B' 
-} 

type B a = ReaderT String (ReaderT Int IO) a 
{- OK -} 

main = do 
    r <- flip runReaderT 39 $ do 
      n <- ask :: A Int 
      s <- flip runReaderT "foo" $ (ask :: B String) 
      return $ n + length s 
    print r 

¿Hay una manera de evitar la expansión del tipo de sinónimos A en la definición de B a ?

Respuesta

12

Los sinónimos de tipo no se pueden aplicar parcialmente. En este caso específico, puede escribir

type A = ReaderT Int IO 
type B a = ReaderT String A a 

[o incluso mejor type B = ReaderT String A utilizar B en otro transformador mónada]

Es en general, que la transformación es imposible sin el uso de Newtype/datos, por ejemplo:

type A a = Reader a Int 

no se pueden escribir equivalentemente como type A = .... En cierto sentido, esta característica sería equivalente a lambda a nivel de tipo \a -> Reader a Int.

Cuestiones relacionadas