Pregunta

Tengo un problema con el alcance de Haskell en las definiciones de where . Cuando tengo la siguiente función f , donde quiero pasar el x a la función localmente definida f1 sin usarla explícitamente como parámetro, Recibo un error que dice que el tipo de x es incompatible con el de la salida de f1 , aunque debería ser el mismo:

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

El error es el siguiente:

    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.

Sin embargo, cuando paso el x como un parámetro adicional, como hice en el siguiente código con la función g , funciona bien:

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

¿Hay alguna manera de hacer que el tipo a en f sea compatible con el tipo a (o a1 ) en f1 ?

¿Fue útil?

Solución

El problema con su código es la firma de tipo f1 de ámbito local. Especifica que f1 puede tomar cualquier tipo

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

Aunque esta es una función local, ha generalizado esta función para poder tomar un tipo que no existirá dentro de f, lo que sea que esta función reciba TIENE que venir de f, por lo que la firma de tipo es innecesaria.

Simplemente elimine la firma de tipo f1.

Editar: Leer mi publicación para mí mismo, no está claro. a en f1 es un tipo parametrizado que puede tomar cualquier cosa, pero los argumentos que se le pasan ya están vinculados en f. Por lo tanto, esta función solo puede recibir lo que recibe su función principal, la firma de tipo que le está dando rompe esa regla. Espero que sea un poco más claro.

Otros consejos

Dave está justo arriba. Otra forma de pensarlo es que, aunque ambas firmas de tipo se refieren a la variable a , en realidad no es la misma variable de tipo. En la notación de Haskell-prime, ambas firmas pueden escribirse más explícitamente como:

para todos a. Eq a = > a - > [a]

lo que significa que para ambas funciones, pueden aceptar un argumento de cualquier tipo (dentro de la ecuación). Obviamente, este no es el caso aquí. En Haskell 98 estándar, la única opción es renunciar a la firma de tipo para f1 . Pero GHC (¿y otros?) Admiten léxico variables de tipo con ámbito . Para que puedas escribir

{-# LANGUAGE ScopedTypeVariables #-}

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

y eso funcionaría bien.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top