[Haskell] Polimorfismo sopra e sotto il where

Messaggioda kaspar » 28/05/2021, 17:33

Ciao :smt039

Non so come esprimere bene il problema per poi magari cercare una soluzione da me. Quindi faccio un esempio:

Codice:
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:

Codice:
[...] 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 a in pratica. Come faccio a dire al compilatore "per helper voglio proprio quella a del tipo di slurp"?
kaspar
Junior Member
Junior Member
 
Messaggio: 177 di 495
Iscritto il: 17/11/2019, 09:58

Re: [Haskell] Polimorfismo sopra e sotto il where

Messaggioda apatriarca » 31/05/2021, 11:57

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):
Codice:
{-# 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)

Codice:
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.
apatriarca
Moderatore
Moderatore
 
Messaggio: 5555 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [Haskell] Polimorfismo sopra e sotto il where

Messaggioda kaspar » 01/06/2021, 19:41

Perfetto, funziona.

apatriarca ha scritto: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 modi1. Ma volevo sapere come fare precisamente questa cosa.

Note

  1. La più ovvia:
    Codice:
    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)
kaspar
Junior Member
Junior Member
 
Messaggio: 178 di 495
Iscritto il: 17/11/2019, 09:58


Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite