2010-08-28 18 views
17

Estoy repasando los problemas del libro de Haskell O'Reilly. El problema que estoy trabajando esBeginning Haskell - Obteniendo el error "no en alcance: constructor de datos"

Using the binary tree type that we defined earlier in this chapter, 
write a function that will determine the height of the tree. The height 
is the largest number of hops from the root to an Empty. For example, the 
tree Empty has height zero; Node "x" Empty Empty has height one; 
Node "x" Empty (Node "y" Empty Empty) has height two; and so on. 

estoy escribiendo mi código en un archivo llamado ch3.hs. Aquí está mi código:

36 data Tree a = Node a (Tree a) (Tree a) 
37    | Empty 
38    deriving (Show) 
39 
40 --problem 9:Determine the height of a tree 
41 height :: Tree -> Int 
42 height (Tree node left right) = if (left == Empty && right == Empty) then 0 else max (height left) (height right) 

abriendo ghci en la terminal y escribiendo: load ch3.hs. Cuando lo hago me sale el siguiente error:

Prelude> :load ch3.hs 
[1 of 1] Compiling Main    (ch3.hs, interpreted) 

ch3.hs:42:7: Not in scope: data constructor `Tree' 
Failed, modules loaded: none. 

espero que el constructor de datos de árbol debe estar allí, porque la he definido en las líneas anteriores el método de altura. Pero cuando intento cargar el archivo, me dicen que el constructor de datos no está dentro del alcance. Agradezco su ayuda y la explicación de por qué ocurre este error. Gracias, Kevin

Respuesta

21

Cambio

height (Tree node left right) 

a

height (Node node left right) 

Eso significa que el patrón de coincidencia trabajos sobre los constructores de la algebraic data type (ADT). Tree no es un constructor, es el nombre del ADT.

Por cierto, tiene que comentar su declaración de firma de función para compilar el código porque contiene un error.

entonces usted puede comprobar el tipo inferido a través de

 
:t height 

en ghci o hugs.

+1

Gracias, que trabajado. Todavía no entiendo completamente lo que está pasando, y ahora recibo errores en tiempo de ejecución, pero seguiré mirando y pensando y depurando. –

+3

Otro ejemplo puede hacer que sea más fácil de entender. Imaginemos que estamos trabajando con enteros, no con árboles. Int es el nombre del tipo entero. No puede agregar "Int + Int" porque Int es el nombre del tipo, no un constructor que devuelve un valor de ese tipo. Cosas como 0, 1, 2, ... son los constructores, y si quieres trabajar con enteros, así es como los consigues en tu programa. Aplicando esto a su caso, 'Tree' es el nombre del tipo, y' Node' (o 'Empty') es la forma en que obtiene un * * de ese tipo. El – jrockway

+0

HaskellWiki también tiene una sección útil, e incluso se utiliza como árbol del ejemplo: http://www.haskell.org/haskellwiki/Constructor – jrockway

2

Usted patrón-partido contra constructores, es decir, los casos , de su Tree ADT. Tree es lo que los resume a todos.

Es mucho más sencillo como esto, y, sobre todo, correcta:

height Empty = 0 
height (Node _ l r) = 1 + max (height l) (height r) 
+2

-1 Esto está mal. Pruebe con 'altura (Nodo 1 (Nodo 2 Vacío Vacío) (Nodo 3 Vacío Vacío))'. Debe ser 2, es 0 - es 0 para cualquier entrada, debido a la misma falla que tiene el OP. – delnan

+0

Gracias. Todavía estoy tratando de acostumbrarme a la coincidencia de patrones. Marqué la otra respuesta correcta porque la pregunta era sobre el constructor de datos, pero esto también es útil. –

+0

Fijo - necesidad de añadir 1 al valor de máx (altura izquierda) (altura derecha) por lo que no continuará para volver 0. –

6

Su código es incorrecto, en varios niveles. Parece que no entendiste los tipos de datos algebraicos.

  • El tipo de firma que está mal, un Tree es siempre una Tree de un tipo específico - que se llama a en su declaración, y que pueden ser de cualquier tipo (ya que no es restricción). Entonces, heigth tiene que tomar un Tree de algún tipo - un Tree SomeType, también. Puede y debe usar el tipo más genérico para SomeType, es decir, una variable de tipo como a.
  • Cuando se hace una coincidencia de patrón, debe nombrar un constructor específico - Node a (Tree a) (Tree a) o Empty - para que coincida, no contra el tipo como un todo.Entonces height (Node ...) coincidiría con Node, height (Empty) coincidiría con Empty, y height (Tree ...) intentaría hacer coincidir un constructor llamado Tree, pero no hay ninguno. Ese es el mensaje de error que recibe.
  • Nunca jamás comparar (a través de ==) con un constructor. Realmente funcionaría si escribieras deriving (Show, Eq). Pero debe usar la coincidencia de patrones para determinar si llegó a Empty
  • Lo que lleva a: Solo está haciendo coincidir Node, no Empty - debe agregar una cláusula para Empty.
  • Además, su función sigue devolviendo 0 para todas las entradas si se fija todas las cuestiones antes mencionadas. Nunca regrese otra cosa que 0 o el máximo de los niños height - que puede, a su vez, sólo se devuelven 0 o el máximo de sus niños height, etc ad infinitum. Usted tiene que incrementar el resultado en cada nivel;)
+1

+ 1. Gracias por la ayuda. Empecé hace poco y aún me estoy acostumbrando al nuevo idioma. –

Cuestiones relacionadas