Куда прячется ленивость и как ее оттуда достать?

Oct 31, 2014 20:16

Мы привыкли, что правая свертка (foldr) хорошо заточена для работы с бесконечными списками:

> let mapPlusPi = foldr (\x xs -> (x+pi):xs) []
> head $ mapPlusPi [1..]
4.141592653589793
К сожалению, иногда возникают неприятности. Вот функция, которая берет список и выкидывает из него элементы стоящие на нечетных местах:

> let evenOnly = snd . foldr ( Read more... )

fprog, haskell, сборник задач и упражнений по Хаскелю, fp

Leave a comment

Comments 14

voidex October 31 2014, 17:53:51 UTC
Я с телефона, поэтому больше гадаю, но предположительно надо избавиться от разбора кортежа, например, добавив там ~

Reply

deni_ok October 31 2014, 18:17:46 UTC
Бинго!

Reply


pod_baobabom October 31 2014, 17:59:42 UTC
Ну вот примерно так.

let evenOnly = snd . foldr (\x z -> let (os,es) = z in (x:es,os)) ([],[])

В оригинальном примере явный pattern matching в параметре автоматически делает функцию строгой по второму аргументу. Что происходит внутри -- хорошо видно при вызове ghc -O -ddump-stranal. В первом случае demand на параметер -- (S,1*U), во втором -- (L,U(1*U,1*U)).

Reply


sassa_nf October 31 2014, 19:06:58 UTC
let evenOnly = snd . foldr (\x ~(os,es) -> (x:es, os)) ([],[])

а почему именно - надо подумать.

Reply

sassa_nf October 31 2014, 19:49:08 UTC
а, нутк, довольно странно это, конечно, но выходит, что pattern-match не может доказать, что он irrefutable, а потому должен быть strict.

Т.е. например вот здесь:

let bla = foldr(\x (y:t) -> x:t) [0]

понятно, что поскольку у списка есть два конструктора, то нужно убедиться, что y:t, а не []. А вот у тупля только один конструктор, так что, не ясно, что его останавливает лениво матчить.

Reply

voidex October 31 2014, 20:00:28 UTC
То, что помимо (,) у кортежа есть ещё один конструтор: _|_

Reply


thedeemon October 31 2014, 19:16:38 UTC
Анализатор суровости слишком суров. Т.е. строгости. :)

Reply


gds October 31 2014, 21:28:38 UTC
и почему людям по приколу каждый раз вспоминать, где строго, а где лениво в этом вашем х-е? Чем более явно из кода видна его производительность, тем лучше.

Reply

nivanych October 31 2014, 23:01:22 UTC
Иными словами, у повсеместной ленивости есть только один существенный недостаток -
большая непривычность (но не сложность!) рассуждения за costs semantics.
Что довольно сильно, не буду спорить.

Reply

gds October 31 2014, 23:23:45 UTC
и сложность тоже есть -- надо помнить, где что лениво, а где строго. В данной задаче пришлось вспомнить/узнать, что есть волшебное "~" перед паттерном, которое делает лениво. Чем меньше помнить (иметь заученных наизусть знаний), тем проще.

" = "

Reply

alexandermarkov October 31 2014, 23:07:33 UTC
Язык надо знать, дубина!

Reply


Leave a comment

Up