Невозможно вывести экземпляр с помощью оценщика

Я начал работать через http://www.cs.nott.ac.uk/~pszgmh/monads для введения в курс функционального программирования. Что может быть лучше, чтобы попытаться понять что-то, чем на самом деле попробовать и протестировать код.

Увы, на второй странице встречаю следующее:

data Expr = Val Int | Div Expr Expr

eval            :: Expr -> Int 
eval (Val n)    = n 
eval (Div x y)  = eval x `div` eval y

Который выдает ошибку, когда я пытаюсь запустить его. Я не совсем уверен, почему это происходит. Когда я пытаюсь

eval (Val 4) `div` eval (Val 2) 

в repl-loop он работает просто отлично, но

eval 4 `div` eval 2 

Заканчивается ошибкой вывода типа.

Когда я обновляю свое определение до следующего:

data Expr = Val Int | Div Expr Expr

eval            :: Expr -> Int 
eval (Val n)    = n 
eval (Div x y)  = eval (Val x) `div` eval (Val y)

Я получаю ошибку типа в определении. Что не так с первым определением? Кстати, в курсе используются объятия.


person Apeiron    schedule 06.12.2015    source источник


Ответы (1)


Что eval ожидает, так это аргумент типа, для которого определен eval. Судя по подписи, для нее требуется аргумент типа Expr, либо Val, либо Div. eval 4 означает, что вы передаете Int функции. Чтобы это работало, eval должно быть определено как:

eval :: Int -> Int

Написав (Val 4), вы вызываете один из конструкторов данных типа Expr, создавая новое значение типа Expr, которое вы можете передать eval и осчастливить компилятор.

person Kapol    schedule 06.12.2015
comment
Да, я понимаю это, но тогда почему не работает eval (Div (Val 4) (Val 2)) или eval (Div (eval Val 4) (eval Val 2))? - person Apeiron; 06.12.2015
comment
@Apeiron Я попробовал eval (Div (Val 4) (Val 2)), и это работает. Результат 2. eval (Div (eval Val 4) (eval Val 2)) не работает, потому что eval Val 4 приведет к Int, и вы не можете использовать Int в конструкторе Div - вам нужен Expr. - person Kapol; 06.12.2015