Лень в языке - PullRequest
       18

Лень в языке

5 голосов
/ 16 ноября 2011

Я понимаю, что если бы у меня было утверждение c = a и b, если a было ложным, то компилятор не стал бы оценивать b, он знал бы результат, потому что a уже ложно.

Однако что если яимел функцию, которая была рекурсивной и объединяла рекурсивные вызовы.

So myfunc input1 input2 = and[myfunc(input1),myfunc(input2)]

, если функция, возвращенная из какой-либо точки в вышеупомянутом дереве рекурсивных вызовов функций, вернула false, вызовы рекурсивной функции прекратились бы и значение falseбудет оцениваться в исходной точке вызова?

Другими словами, будет ли он использовать ленивую оценку выше?

Ответы [ 4 ]

8 голосов
/ 16 ноября 2011

Да. Фактически, one реализация and является рекурсивной (и не добавляет никакой строгости):

and :: [Bool] -> Bool
and []     =  True
and (x:xs) =  x && and xs

Чтобы показать, что это работает, вы можете передать бесконечный список False с and и увидеть, что он возвращает

Prelude> and (repeat False)
False

Обратите внимание, однако, что это не работает с бесконечным списком True с, потому что он всегда будет искать False, но никогда не найдет его.

6 голосов
/ 16 ноября 2011

Короче говоря, ответ таков: да, Haskell будет ленив в рекурсивных функциях.

Лень && не является особым случаем: это следствие его определения:

(&&) :: Bool -> Bool -> Bool
True  && y = y
False && _ = False

Здесь лень Хаскелла означает, что он может сопоставить первый аргумент с &&, и второй аргумент не нужно оценивать, чтобы узнать результат.

Для рекурсивной функции, такой как and у нас есть определение:

and :: [Bool] -> Bool
and []     = True
and (b:bs) = b && and bs

Это рекурсивное определение, Haskell ленив в том, что значения b и bs в непустом списке будут оцениваться только при необходимости:в этом случае определение && заставляет нас взглянуть на первый элемент b, а если он равен False, то остальные значения bs не нужно оценивать.

Урок здесь заключается в том, что лень - это то, что Haskell предоставляет благодаря сопоставлению с образцом: когда потребляется достаточное количество входных данных для сопоставления с образцом, остальные могут быть оставлены без оценки до тех пор, пока это не потребуется.

2 голосов
/ 29 ноября 2011

если функция, возвращенная из какой-либо точки в вышеупомянутом дереве рекурсивных вызовов функций, вернула false, вызовы рекурсивной функции прекратятся и значение false будет просто оценено в исходной точке вызова?

Вы можете писать рекурсивные вызовы, основанные на этом поведении.Например, следующая функция exists в OCaml возвращает true, если результат применения данной функции предиката p к каждому элементу в списке возвращает true для любого элемента:

let rec exists p = function
  | [] -> false
  | x::xs -> p x || exists p xs

Благодаря оценке короткого замыкания это прекратит итерацию по списку, как только p вернет true в первый раз.

Другими словами, будет ли он использовать ленивую оценку выше?

Обратите внимание, что это оценка короткого замыкания , а не лень.

2 голосов
/ 16 ноября 2011

Я новичок в Haskell, но да, он будет оценивать все дерево рекурсивных вызовов с левой стороны и, и только если они наконец вернут true, он перейдет к оценке рекурсивных вызовов справа.

На самом деле, ни один из них не будет оцениваться до тех пор, пока вы не закончите использовать результат my_func в чем-то похожем на печать, но вышеприведенное стоит, если вы уже принудительно оценили my_func.

Думайте об этом как о прохождении обещания обойти все, что он делает. Таким образом, результат вызова my_func не результат, это обещание выяснить. Вероятно, он даже не думал о том, что означает это обещание, пока не должен. Только тогда он входит и выясняет, что он должен назвать.

Возможно, я ухожу, но я так понимаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...