Domanda

Ho un problema con l'ambito di Haskell nelle definizioni dove . Quando ho la seguente funzione f , dove voglio passare x alla funzione definita localmente f1 senza usarlo esplicitamente come parametro, Viene visualizzato un errore che indica che il tipo di x è incompatibile con quello nell'output di f1 , sebbene dovrebbe essere lo stesso:

f :: Eq a => a -> [a]
f x = f1 x
    where
        f1 :: Eq a => a -> [a]
        f1 y = [ x, y ]

L'errore è il seguente:

    Couldn't match expected type `a1' against inferred type `a'
      `a1' is a rigid type variable bound by
           the type signature for `f1' at test.hs:4:11
      `a' is a rigid type variable bound by
          the type signature for `f' at test.hs:1:8
    In the expression: x
    In the expression: [x, y]
    In the definition of `f1': f1 y = [x, y]
Failed, modules loaded: none.

Quando invece passo x come parametro aggiuntivo, come ho fatto nel seguente codice con la funzione g , funziona benissimo:

g :: Eq a => a -> [a]
g x = g1 x x
    where
        g1 :: Eq a => a -> a -> [a]
        g1 x y = [ x, y ]

Esiste un modo per rendere il tipo a in f compatibile con il tipo a (o a1 ) in f1 ?

È stato utile?

Soluzione

Il problema con il codice è la firma del tipo f1 con ambito locale. Specifica che f1 può assumere qualsiasi tipo

f1 :: Eq a = > a - > [A]

Anche se questa è una funzione locale, hai generalizzato questa funzione per essere in grado di assumere un tipo che non esisterà all'interno di f, qualunque cosa questa funzione riceva DEVE provenire da f, quindi la firma del tipo non è necessaria.

Rimuovi semplicemente la firma del tipo f1.

Modifica: rileggo il mio post, non è chiaro. a in f1 è un tipo con parametri che può accettare qualsiasi cosa, ma gli argomenti passati ad esso sono già associati in f. Quindi questa funzione può ricevere solo ciò che riceve la sua funzione genitore, la firma del tipo che stai dando infrange quella regola. Spero che sia un po 'più chiaro.

Altri suggerimenti

Dave è proprio sopra. Un altro modo di pensarci è che anche se entrambe le firme di tipo si riferiscono alla variabile a , in realtà non è la stessa variabile di tipo. Nella notazione Haskell-prime, entrambe le firme possono essere scritte più esplicitamente come:

forall a. Eq a = > a - > [A]

significa che per entrambe le funzioni , possono accettare qualsiasi argomento di qualsiasi tipo (all'interno dell'Eq). Questo ovviamente non è il caso qui. In Haskell 98 standard, l'unica opzione è quella di rinunciare alla firma del tipo per f1 . Ma GHC (e altri?) Supportano lessicalmente variabili di tipo con ambito . Quindi potresti scrivere

{-# LANGUAGE ScopedTypeVariables #-}

f :: forall a. Eq a => a -> [a]
f x = f1 x
    where
        f1 :: a -> [a]
        f1 y = [ x, y ]

e funzionerebbe benissimo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top