2010-02-16 672 views
18

Tengo problemas para entender los funtores, específicamente qué tipo de concreto se encuentra en LYAH. Creo que esto se debe a que no entiendo qué es realmente [].¿Qué es [] (constructor de lista) en Haskell?

fmap :: (a -> b) -> f a -> f b 
  1. Es [], un tipo constructor? O bien, ¿es un constructor de valor?
  2. ¿Qué significa tener el tipo de: [] :: [a]?
  3. ¿Es como Maybe type-constructor o Just value constructor?
    1. Si es así entonces ¿cómo es que JustJust tiene una firma como Just :: a -> Maybe a en lugar de Just :: Maybe a, en otras palabras, ¿por qué no [] mecanografiadas [] :: a -> [a]
  4. LYAH dice esto, ya que se aplica a los funtores: Aviso cómo no escribimos la instancia Functor [a] donde, porque desde fmap :: (a -> b) -> fa -> fb, vemos que f tiene que ser un constructor de tipo que toma un tipo. [a] ya es un tipo concreto (de una lista con cualquier tipo dentro), mientras que [] es un constructor de tipos que toma un tipo y puede producir tipos como [Int], [String] o incluso [[String]]. Estoy confundido, aunque el tipo de [] implica que es como un literal para [a] ¿a qué intenta llegar LYAH?
+1

Y si desea algo de tipo a -> [a], existe la función de aspecto gracioso (: []). –

+0

^O puede usar 'return' (o' pure' u otros): D –

+1

@DanielVelkov: ': []' es ':' parcialmente aplicado a '[]' usando la sintaxis de sección, solo para ser claro. – mk12

Respuesta

15
  1. Es (confusamente, te concedo) sintácticamente sobrecargado para ser a la vez un constructor de tipo y un constructor de datos.

  2. Esto significa que (el valor constructor) [] tiene el tipo que, para todos los tipos a, es una lista de a (que está escrito [a]). Esto se debe a que hay una lista vacía en cada tipo.

  3. El constructor de datos [] no se escribe a -> [a] debido a que la lista vacía no tiene elementos, y por lo tanto no necesita una a para hacer una lista vacía de a 's. Comparar con Nothing :: Maybe a en su lugar.

  4. Lyah está hablando del constructor de tipos [] con clase * -> *, en comparación con el valor constructor [] con el tipo [a].

+5

Puede ser útil saber que, como tipo, '[a]' es azúcar sintáctica para '[] a', que se parece más a cómo se hacen normalmente las cosas para los tipos de mayor kínder. –

8
  1. es un constructor de tipos (por ejemplo, [Int] es un tipo), y un constructor de datos ([2] es una estructura de lista).
  2. La lista vacía es una lista realización de cualquier tipo
  3. [a] es como Tal vez una, [2] es como Sólo 2.
  4. [] es una función cero-ary (una constante) por lo que doesn' t tiene tipo de función.
+1

I * realmente * me gusta la redacción en 4. Creo que tomó la combinación de tu respuesta a 4 y la respuesta de Doug a 3 para tener esto en mi cabeza! Entonces 'Nothing :: Maybe a', y' [] :: [a] 'son los constructores vacíos. '[a]' también es análogo a 'Maybe a' porque ambos son constructores de valores para valores (discretos de Nothing). Conclusión, me confundí con '[]', porque '[]' esencialmente se superpone al constructor de datos de la lista con el constructor de datos de un Array's Nothing, donde como 'Maybe a' tiene dos constructores separados. ¿Estoy en lo correcto? –

5

para hacer las cosas más explícita, este tipo de datos:

data List a = Cons a (List a) 
      | Nil 

... tiene la misma estructura que el tipo incorporado en la lista, pero sin el (mejor, pero potencialmente confuso) especial sintaxis. Esto es lo que algunas correspondencias parecen:

  • List = [], constructores de tipo con * -> *
  • List a = [a], tipos amables con clase *
  • Nil = [], valores con los tipos polimórficos List a y [a] respectivamente
  • Cons = :, constructores de datos con los tipos a -> List a -> List a y a -> [a] -> [a] respectivamente
  • Cons 5 Nil = [5] o 5:[], solo elemento enumera
  • f Nil = ... = f [] = ..., la coincidencia de patrones listas vacías
  • f (Cons x Nil) = ... = f [x] = ... `, patrón de búsqueda de listas de un solo elemento
  • f (Cons x xs) = ... = f (x:xs) = ..., la coincidencia de patrones listas no vacías

De hecho, si le preguntas acerca ghci [], te dice bastante m Uch la misma definición:

> :i [] 
data [] a = [] | a : [a]   -- Defined in GHC.Types 

Pero no se puede escribir una definición tan mismo porque la sintaxis de la lista y su tipo "outfix" Constructor es un caso especial, que se define en la especificación del lenguaje.

+0

¿Podría explicar más sobre la última parte 'a: [a]' en lugar de 'a: []' es la lista vacía '[]' tipeada '[a]', la primera parte de la definición 'data [] = [] | a: [a] ', me dejaría creer que es' [] '. ¿''], También es suficiente con el requisito de '[a]'? –

+0

No estoy seguro de lo que estás preguntando. En 'a: [a]', ':' está definiendo el constructor de datos (como 'Cons'), y' [a] 'está especificando el tipo de un argumento para el constructor (como' List a'). En la primera parte de la definición, '[]' es un constructor de datos sin argumentos, como 'Nil'. Ambas partes producen valores de tipo '[a]', ¡porque eso es exactamente lo que se está definiendo! –

+3

Quizás lo que le está haciendo tropezar es que * los constructores de datos * no tienen que tomar parámetros que representen todos (o ninguno) de los parámetros para * constructor de tipos * En 'datos O a b = A la izquierda a | Derecha b', el constructor de datos 'Left a' todavía crea un valor de tipo' Either a b', aunque no se tenga 'b'. Lo mismo ocurre con 'Nothing' y' [] '. Incluso podría tener algo como 'datos NoValue a b c d e f = Lonely'. Aunque no contiene ningún valor, 'Lonely' sigue obsesionado por el espectro de todos esos parámetros de tipo, manteniéndolo distinto de cualquier' Lonely's con diferentes tipos. –

18

Se describe el tipo (en una sesión GHCi) como:

$ ghci 
Prelude> :info [] 
data [] a = [] | a : [a] -- Defined 

También podemos pensar en ello como si se definieron como:

data List a = Nil 
      | Cons a (List a) 

o

data List a = EmptyList 
      | ListElement a (List a) 

Tipo Constructor

[a] es un tipo de datos polimórficos, que también se puede escribir [] a como se indica anteriormente. Esto puede ser pensado como si fuera List a

En este caso, es un constructor []tipo teniendo un argumento de tipo a y devolver el tipo [] a, que también está permitido escribir como [a].

Uno puede escribir el tipo de una función como:

sum :: (Num a) => [a] -> a 

datos Constructor

[] es un constructor de datos que esencialmente significa "lista vacía." Este constructor de datos no toma argumentos de valor.

Hay otro constructor de datos, :, que antepone un elemento al frente de otra lista. La firma para este constructor de datos es a : [a] - toma un elemento y otra lista de elementos y devuelve una lista de elementos resultante.

La notación [] también se puede utilizar como taquigrafía para la construcción de una lista. Normalmente nos construir una lista como:

myNums = 3 : 2 : 4 : 7 : 12 : 8 : [] 

que se interpreta como

myNums = 3 : (2 : (4 : (7 : (12 : (8 : []))))) 

pero Haskell nos permite también utilizar la abreviatura

myNums = [ 3, 2, 4, 7, 12, 8 ] 

como un equivalente en significado, pero ligeramente más agradable en apariencia, notación.

caso ambiguo

Hay un caso ambiguo que se ve comúnmente: [a]. Según el contexto, esta notación puede significar "una lista de a" o "una lista con exactamente un elemento, es decir, a". El primer significado es el significado previsto cuando [a] aparece dentro de un tipo, mientras que el segundo significado es el significado previsto cuando [a] aparece dentro de un valor .

+0

¿Debería ser 'suma :: (Num a) => [a] -> a' (con a ** -> **)? – psmears

+0

@psmears - Sí, gracias. – yfeldblum

Cuestiones relacionadas