Haskell - Используй Just or no Только что сделал разницу, но я не знаю почему - PullRequest
4 голосов
/ 16 июля 2010

Я нашел такой код в книге "Real World Haskell", стр. 68

data Tree a = Node a (Tree a) (Tree a)
            | Empty
              deriving (Show)

nodeAreSame (Node a _ _) (Node b _ _)
            | a == b = Just a
nodeAreSame _ _ = Nothing

Мой вопрос: какую работу выполнял конструктор данных Just?Когда я его удаляю, я получаю сообщение об ошибке, например

(in ghci)
......
<Main *> nodeAreSame (Node 3 Empty Empty) (Node 3 Empty Empty))  

<interactive>:1:16:  
    No instance for (Num (Maybe a))
......

Но когда я пытаюсь сравнить разницу типов между версиями "Just" и "No Just":

nodeAreSameJust   :: (Eq t) => Tree t -> Tree t -> Maybe t

nodeAreSameNoJust :: (Eq a) => Tree (Maybe a) -> Tree (Maybe a) -> Maybe a

Так в чем здесь ключевой момент?Означает ли это, что когда я помещаю переменную с типом a в узел, функция не будет выводить узел с типом a, поэтому получит ошибку?

Ответы [ 3 ]

12 голосов
/ 16 июля 2010

Фактически, отсутствие Just делает не ошибочным.

Вот сделка.Код nodeAreSame (Node a _ _) (Node b _ _) | a == b = a nodeAreSame _ _ = Nothing

хорошо напечатан при условии, что a и b имеют тип Maybe t для некоторых t, поскольку это тип Nothing,Таким образом, система типов делает этот вывод.

Теперь, когда у вас есть числовой литерал, такой как 3, предполагается, что он имеет тип Num s => s, пока вы фактически не передадите его определенному типу данных (например, Int или Double).

Таким образом, когда он объединяет эти два факта, он предполагает следующее:

Num (Maybe t) => 3 :: Maybe t.

Поскольку нет экземпляра дляNum (Maybe t), в этот момент он жалуется, прежде чем получает возможность жаловаться, что 3 :: Maybe t не имеет смысла.

3 голосов
/ 16 июля 2010

Что еще вы ожидаете вернуть, просто a? Это не сработает, потому что a и Nothing не одного типа. Все определения функции должны возвращать один и тот же тип. Nothing и Just a совпадают, потому что они оба типа Maybe a.

2 голосов
/ 16 июля 2010

В версии no Just требуется, чтобы элемент в дереве имел тип Maybe a.

Я не совсем уверен, что причина ошибки, например, в Num (возможно). Я думаю, что ошибка более поучительна, если вы используете строку вместо 3.

*Main> nodeAreSameNoJust (Node "arst" Empty Empty) (Node "arst" Empty Empty)
<interactive>:1:24:

Couldn't match expected type `Maybe a'
       against inferred type `[Char]'
In the first argument of `Node', namely `"arst"'
In the first argument of `nodeAreSameNoJust', namely
    `(Node "arst" Empty Empty)'
In the expression:
    nodeAreSameNoJust
      (Node "arst" Empty Empty) (Node "arst" Empty Empty)

Здесь более ясно, что он ожидает что-то типа Может быть. В обоих случаях вторым случаем функции является Nothing, поэтому тип результата выводится как Maybe a. Включив Just, значение, которое вы используете в дереве, затем помещается в тип Maybe. Без этого он ожидает, что результирующий a будет того же типа, что и Nothing, поскольку каждая часть функции должна быть одного типа.

...