он не должен выдавать ошибку, так как эта часть даже не оценивается.
Тот факт, что она не оценивается, не имеет значения.Haskell является статически типизированным языком, и компилятор проверяет типы.Не нужно вычислять результат, чтобы проверить тип значения: тип ввода и вывода всех функций известен (хорошо рассчитан), а компилятор Haskell проверяет, что тип вывода одной функции совпадает с типом вводафункция, которая вызывается для обработки этого вывода.
Проверка типов выполняется в время компиляции , а компилятор Haskell не ленив (в том смысле, что он выполняетэти проверки перед генерацией двоичного файла, а не только перед запуском кода).Компилятор охотно проверяет типы и гарантирует, что программа чувствительна с точки зрения системы типов.
Например, следующее выражение будет проверять тип:
1 : 2 : undefined
, но undefined :: a
вызовет ошибку в случае ее оценки.
Haskell позволяет определять новые типы Num
bers, так что вы можете создать класс типов, который будет анализировать числа 4
,5
и 3
на номера вашего собственного типа.Этот тип может быть, строго говоря, списком.
Но Haskell, если вы оцените это, не найдет тип для использования и выдаст ошибку:
Prelude> safeHead (4:5:3:[]:[])
<interactive>:6:1: error:
• Non type-variable argument in the constraint: Num [t]
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall t. Num [t] => Maybe [t]
Так что вот оноищет тип для элементов списка и обнаруживает, что это должны быть списки, из-за элемента []
(один, но последний элемент), но в то же время они должны быть Num
s,теперь он не может найти такой тип, поэтому возникает ошибка.
Мы можем, строго говоря, создать такой тип, чтобы мы могли использовать функцию надлежащим образом:
Prelude> data A = A deriving Show
Prelude> :{
Prelude| instance Num [A] where
Prelude| (+) = undefined
Prelude| (*) = undefined
Prelude| abs = undefined
Prelude| fromInteger _ = [A]
Prelude| negate = undefined
Prelude| signum = undefined
Prelude| :}
Prelude> :{
Prelude| safeHead :: [a] -> Maybe a
Prelude| safeHead [] = Nothing
Prelude| safeHead (x:_) = Just x
Prelude| :}
Prelude> safeHead (4:5:3:[]:[]) :: Maybe [A]
Just [A]