Я хочу реализовать функцию с именем log2, которая вычисляет целочисленный журнал (по основанию 2) своего аргумента. Я не могу использовать функцию журнала. Мое решение: проверить, равен ли x 2 ^ y. Если x равно 2^y, введите значение y, если x не равно 2^y, тогда y = y + 1. Это будет продолжаться до тех пор, пока не будет найдено y. Это то, что я получил до сих пор:
log2 x = y where y = 0
if x == 2^y then y
else y = y + 1
Когда я хочу запустить это, я получу эту ошибку:
error: parse error on input `if'
Я новичок в Haskell, может кто-нибудь объяснить мне, что не так?
Нужно ли мне помещать оператор if и else под оператором where или как?
Трудно точно объяснить, почему возникает синтаксическая ошибка, учитывая, что не очевидно, какому (действительному) синтаксису она предназначена. Достаточно сказать, что вы по существу написали log2 x = 0
if .....
. Можно было бы ожидать, что вторая фраза будет определением или частью того же выражения, что и 0
, но if
не начинается ни с того ни с сего.
В более общем случае в Haskell нет изменяемых переменных. Вы не можете «назначить» на y
. Ближе всего к тому, что вы хотите, будет что-то вроде
log2 x = until (\y -> x == 2^y) (\y -> y + 1) 0
Обратите внимание, что мы никогда не присваиваем y
, мы просто привязываем его для выполнения каждого лямбда-выражения. Мы можем представить, что каждый раз он получает новое имя! и это было бы хорошо.
Спасибо за ваше объяснение, если я запущу это и использую 10 для x, это не сработает. Но если я использую 4 вместо x, это будет. Как это возможно и как мы можем это исправить?
Ну, ваша исходная программа работает только для точных степеней 2
, верно? Один из способов улучшить его — написать >=
вместо ==
, тогда, по крайней мере, он остановится на 10
. Но вам понадобится что-то более сложное, чем добавлять 1
каждую итерацию, чтобы найти точные логарифмы.
Haskell использует отступы и интервалы для обозначения области выражений. Ваше утверждение
if
имеет такой отступ, который указывает на то, что оно находится за пределами пунктаwhere
.