Haskell - использовать Just или no Just имеет значение, но я не знаю, почему

Я нашел такой код в книге "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, поэтому она получает ошибку?


person snowmantw    schedule 16.07.2010    source источник


Ответы (3)


На самом деле отсутствие 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 не имеет смысла.

person intoverflow    schedule 16.07.2010

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

person Adam Crume    schedule 16.07.2010

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

Я не совсем уверен, что причина ошибки, например, в Num (возможно, a). Я думаю, что ошибка более информативна, если вы используете строку вместо 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)

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

person arsenm    schedule 16.07.2010