2009-12-01 13 views
8

Ho una domanda Haskell typeclass. Non riesco a mescolare la sintassi per ottenere questo (apparentemente ragionevole) programma da compilare sotto GHC.Haskell typeclass

import Control.Concurrent.MVar 

blah1 :: [a] -> IO ([a]) 
blah1 = return 

blah2 :: [a] -> IO (MVar [a]) 
blah2 = newMVar 

class Blah b where 
    blah :: [a] -> IO (b a) 

instance Blah [] where 
    blah = blah1 

-- BOOM 
instance Blah (MVar []) where 
    blah = blah2 

main :: IO() 
main = do 
    putStrLn "Ok" 

ottengo il seguente messaggio di errore, che tipo di senso, ma non so come risolvere il problema:

`[]' is not applied to enough type arguments 
Expected kind `*', but `[]' has kind `* -> *' 
In the type `MVar []' 
In the instance declaration for `Blah (MVar [])' 

risposta

12

Quello che vuoi non è direttamente esprimibili. Questo è probabilmente il più vicino si otterrà:

newtype MVarList a = MVarList (MVar [a]) 
instance Blah MVarList where 
    blah = fmap MVarList . newMVar 
+0

Ho provato a giocare con questo per capire perché un'istanza di 'Blah' dove' blah' restituisce 'IO (MVar [a])' ​​non è possibile. È perché la variabile di tipo "b" nella definizione di classe di "Blah" deve riferirsi a un singolo tipo? –

+0

Sembra che la variabile di tipo "b" debba essere di tipo * -> *, e non c'è modo di scrivere un'espressione di tipo da "MyType -> MVar [MyType]". –

+1

corretto. Per le funzioni esiste '(.) :: (b -> c) -> (a -> b) -> a -> c' ma non esiste una composizione per i tipi rank-1 (o rank-n). – ephemient

2

stavo leggendo biblioteca di Conal Elliott TypeCompose, e sono ricordato di questa domanda. Ecco un esempio di come puoi eseguire la composizione a livello di testo.

{-# LANGUAGE TypeOperators #-} 
{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE TypeSynonymInstances #-} 
module Main where 

... 

import Control.Compose 

... 

instance Blah (MVar `O` []) where 
    blah = liftM O . blah2 

... 
Problemi correlati