Ошибка типа Миранда
Может кто-нибудь сказать мне, где идет не так?
b f x = f x (f x)
Я понимаю так: потому что f
слева принимает один аргумент, а с правой стороны - два аргумента?
Есть более подробные объяснения?
2 ответа
Давайте попробуем построить этот тип:
b :: ... ?
У нас есть как минимум два аргумента, поэтому давайте изменим b
соответственно:
b :: a -> c -> d
Правая сторона b
предполагает, что f
это функция. Давайте сначала коснемся только первого аргумента:
f :: c -> e
До сих пор все складывалось довольно неплохо: первый аргумент списка имеет тот же тип, что и второй аргумент b. Давайте продолжим на правой стороне.
f x (f x)
Если мы возьмем f x _
, мы должны предположить, что e
является e :: k -> l
мы принимаем другой аргумент. Теперь у нас есть
f :: c -> k -> l
Теперь посмотрим на тип f
Второй аргумент Это тип должен быть одним из f x
:
f x :: k -> l
Так k = k -> l
, Это бесконечный тип, который мы также можем увидеть, посмотрев на сообщение об ошибке ghci:
Prelude> let bfx = fx (fx): 2: 18: Происходит проверка: невозможно создать бесконечный тип: t1 = t1 -> t0 В возвращаемом типе вызова `f'Вероятная причина: `f' применяется к слишком немногим аргументам Во втором аргументе `f', а именно`(f x)' В выражении: f x (f x)
Проверка типов сдается, поскольку бесконечный тип не может быть им построен. В конце концов, это происходит, так как вы подаете заявку f
на другое количество аргументов.
Компилятор пытается определить тип f
, Сначала он видит, что f
принимает аргумент x
и еще один аргумент (f x)
, который на данный момент мы подставим как y
, Поэтому, когда компилятор видит что-то вроде f x y
это означает, что f
имеет тип a -> b -> c
, с x :: a
, y :: b
, а также f x y :: c
, Затем он проверяет y
ближе, видя, что его тип более конкретно b -> c
, так как он уже знает f
должен иметь второй аргумент. Так что теперь можно определить, что b ~ b -> c
, И это где он должен остановиться, как можно b
также b -> c
? Если он продолжал заменять b ~ b -> c
, он будет иметь бесконечную рекурсию, пытаясь выяснить, какой тип b
является! Это, очевидно, не может работать, поэтому он выдает ошибку компиляции, говоря, что он не может создать бесконечный тип b = b -> c
(примечание: в сообщении об ошибке могут использоваться имена, отличные от b
или же c
). Сообщение об ошибке, которое я получаю, на самом деле очень полезно:
Occurs check: cannot construct the infinite type: t1 = t1 -> t0
In the return type of a call of `f'
Probable cause: `f' is applied to too few arguments
In the second argument of `f', namely `(f x)'
In the expression: f x (f x)
Это говорит вам, где именно проблема, а именно (f x)
"и дает вам вероятную причину"f
применяется к слишком немногим аргументам ", говоря, что" не может создать бесконечный тип t1 = t1 -> t0
".