Dado el siguiente tipo algebraico:

ghci> data Foo a = Foo a

Luego instancia uno de ellos.

ghci> let f = Foo "foo"

Por último, me gustaría llamar a fmap para aplicar una función como (a -> b) -> Foo a -> Foo b.

ghci> fmap (++ "bar") f

<interactive>:78:1:
    No instance for (Functor Foo) arising from a use of ‘fmap’
    In the expression: fmap (++ "bar") f
    In an equation for ‘it’: it = fmap (++ "bar") f

Pero, como no implementé una instancia Functor de Foo, no puedo usar fmap.

¿Hay alguna forma de obtener Functor instancias de forma gratuita? No tengo ningún conocimiento del compilador de Haskell, pero tal vez sea lo suficientemente inteligente como para saber que fmap en Foo a simplemente se aplica (a -> b) a Foo a.

3
Kevin Meredith 8 feb. 2015 a las 17:44

2 respuestas

La mejor respuesta

Trabajando en ghci, si haces el encantamiento

Prelude> :set -XDeriveFunctor

Entonces el compilador se volverá tan inteligente como usted espera, si no tan entusiasta. Deberá invocar la funcionalidad, por lo tanto,

Prelude> data Foo a = Foo a deriving (Show, Functor)

(el Show es solo para imprimir el resultado, a continuación) y luego podrá hacer cosas como

Prelude> fmap (++"bar") (Foo "foo")
Foo "foobar"

En un módulo, logras lo mismo agregando el pragma

{-# LANGUAGE DeriveFunctor #-}

Antes de la declaración module. Es bueno para al menos las instancias Functor más sencillas, pero puede engañarlo y convertirlo en un falso negativo.

Prelude> data Boo a = Boo (Either a Bool) deriving Functor

<interactive>:9:43:
    Can't make a derived instance of ‘Functor Boo’:
      Constructor ‘Boo’ must use the type variable only as the
        last argument of a data type
      In the data declaration for ‘Boo’

Mientras tanto

data Goo a = Goo (Either Bool a) deriving Functor

Está bien, y la maquinaria claramente ha sido pirateada para que funcione con el emparejamiento, como

data Woo a = Woo (a, Bool) deriving Functor

Esta permitido.

Así que no es tan inteligente como podría ser, pero es mejor que un golpe en el ojo.

10
pigworker 8 feb. 2015 a las 15:04

Seguro que puede, agregue deriving Functor a su declaración de datos y {-# LANGUAGE DeriveFunctor #-} en la parte superior del archivo.

4
arrowd 8 feb. 2015 a las 14:58