2015-03-26 12 views
5

Ho un esempio di funzione, in cui non riesco a scrivere un tipo nella clausola where. replace è una funzione che sostituisce tutti gli X di Y in un dato elenco.Haskell: dichiarazione di tipo in `where`

replace :: (Eq a) => a -> a -> [a] -> [a] 
replace x y xs = map helper xs 
    where 
    helper :: (Eq a) => a -> a 
    helper = (\el -> if el == x then y else el) 

Quando provo a compilare questa funzione si ottiene un errore:

ProblemsArithmetics.hs:156:31: 
Could not deduce (a ~ a1) 
from the context (Eq a) 
    bound by the type signature for 
      replace :: Eq a => a -> a -> [a] -> [a] 
    at ProblemsArithmetics.hs:152:12-41 
or from (Eq a1) 
    bound by the type signature for helper :: Eq a1 => a1 -> a1 
    at ProblemsArithmetics.hs:155:15-30 
    ‘a’ is a rigid type variable bound by 
     the type signature for replace :: Eq a => a -> a -> [a] -> [a] 
     at ProblemsArithmetics.hs:152:12 
    ‘a1’ is a rigid type variable bound by 
     the type signature for helper :: Eq a1 => a1 -> a1 
     at ProblemsArithmetics.hs:155:15 
Relevant bindings include 
    el :: a1 (bound at ProblemsArithmetics.hs:156:16) 
    helper :: a1 -> a1 (bound at ProblemsArithmetics.hs:156:5) 
    xs :: [a] (bound at ProblemsArithmetics.hs:153:13) 
    y :: a (bound at ProblemsArithmetics.hs:153:11) 
    x :: a (bound at ProblemsArithmetics.hs:153:9) 
    replace :: a -> a -> [a] -> [a] 
    (bound at ProblemsArithmetics.hs:153:1) 
In the second argument of ‘(==)’, namely ‘x’ 
In the expression: el == x 

Allo stesso tempo, se tralascio

helper :: (Eq a) => a -> a 

il codice viene compilato bene.

Pur comprendendo la logica dietro di esso (a in replace dichiarazione di tipo e a in helper dichiarazione tipo sono differenti a s), e ci sono almeno 2 soluzioni (omettere dichiarazione di tipo o passare x e y come parametri per helper funzione), la mia domanda è:

C'è un modo per dire al compilatore che intendo lo stesso tipo in entrambe le dichiarazioni di tipo?

+3

Sì: https://wiki.haskell.org/Scoped_type_variables – Jubobs

+2

Prova ad aggiungere '{- # LINGUA ScopedTypeVariables # -}'. Non posso testare ora, chiunque è libero di trasformare il mio commento in una risposta. – Franky

risposta

10

Se si attiva ScopedTypeVariables e si introduce una variabile di tipo con forall, diventa visibile nell'ambito interno.

{-# LANGUAGE ScopedTypeVariables #-} 

replace :: forall a. (Eq a) => a -> a -> [a] -> [a] 
replace x y xs = map helper xs 
    where 
    helper :: a -> a 
    helper = (\el -> if el == x then y else el) 
Problemi correlati