[Haskell] Polimorfismo sopra e sotto il where
Ciao 
Non so come esprimere bene il problema per poi magari cercare una soluzione da me. Quindi faccio un esempio:
L'errore che il compilatore mi mostra è questo:
Mi ha distinto le due [tt]a[/tt] in pratica. Come faccio a dire al compilatore "per [tt]helper[/tt] voglio proprio quella [tt]a[/tt] del tipo di [tt]slurp[/tt]"?

Non so come esprimere bene il problema per poi magari cercare una soluzione da me. Quindi faccio un esempio:
import Control.Conditional import System.IO -- In realtà non è importante sapere cosa fanno le funzioni... slurp :: (String -> a) -> FilePath -> IO [a] slurp f fp = withFile fp ReadMode helper where helper :: Handle -> IO [a] helper hdl = ifM (hIsEOF hdl) (return []) $ do ln <- hGetLine hdl fmap (f ln :) (helper hdl)
L'errore che il compilatore mi mostra è questo:
[...] error: • Couldn't match type ‘a1’ with ‘a’ ‘a1’ is a rigid type variable bound by the type signature for: helper :: forall a1. Handle -> IO [a1] at sand.hs:30:5-30 ‘a’ is a rigid type variable bound by the type signature for: slurp :: forall a. (String -> a) -> FilePath -> IO [a] at sand.hs:27:1-44 Expected type: IO [a1] Actual type: IO [a] [...]
Mi ha distinto le due [tt]a[/tt] in pratica. Come faccio a dire al compilatore "per [tt]helper[/tt] voglio proprio quella [tt]a[/tt] del tipo di [tt]slurp[/tt]"?
Risposte
Dai una occhiata a questa pagina di stackoverflow. In generale le soluzioni dovrebbero essere (non ho accesso in questo momento ad un compilatore per Haskell per cui non posso provare):
Un'altra soluzione è quella di non scrivere la type signature della funzione interna in quanto Haskell dovrebbe essere in quel caso in grado di inserire il tipo corretto da solo.
{-# LANGUAGE ScopedTypeVariables #-} slurp :: forall a. (String -> a) -> FilePath -> IO [a] slurp f fp = withFile fp ReadMode helper where helper :: Handle -> IO [a] helper hdl = ifM (hIsEOF hdl) (return []) $ do ln <- hGetLine hdl fmap (f ln :) (helper hdl)
slurp :: (String -> a) -> FilePath -> IO [a] slurp f fp = withFile fp ReadMode $ helper f where helper :: (String -> a) -> Handle -> IO [a] helper f hdl = ifM (hIsEOF hdl) (return []) $ do ln <- hGetLine hdl fmap (f ln :) (helper hdl)
Un'altra soluzione è quella di non scrivere la type signature della funzione interna in quanto Haskell dovrebbe essere in quel caso in grado di inserire il tipo corretto da solo.
Perfetto, funziona.
Certo. esistono anche altri modi[nota]La più ovvia:
"apatriarca":
Un'altra soluzione è quella di non scrivere la type signature della funzione interna in quanto Haskell dovrebbe essere in quel caso in grado di inserire il tipo corretto da solo.
Certo. esistono anche altri modi[nota]La più ovvia:
import Control.Conditional import System.IO slurp :: (String -> a) -> FilePath -> IO [a] slurp f fp = withFile fp ReadMode (hSlurp f) hSlurp :: (String -> a) -> Handle -> IO [a] hSlurp f hdl = ifM (hIsEOF hdl) (return []) $ do ln <- hGetLine hdl fmap (f ln :) (hSlurp f hdl)[/nota]. Ma volevo sapere come fare precisamente questa cosa.