tgoop.com/haskell_tg/36
Create:
Last Update:
Last Update:
# 🧠 Haskell-задача с подвохом: “print vs lazy evaluation”
📘 Условие
Посмотри на следующий код:
main :: IO ()
main = do
let xs = [1..5]
print (map (\x -> traceShow x (x * 2)) xs)
❓ Вопрос:
1) Что напечатает эта программа?
2) Почему
traceShow
не ведёт себя так, как ожидается? 3) Как заставить
traceShow
сработать для каждого элемента?---
✅ Подвох: ленивость вычислений
Haskell по умолчанию не выполняет вычисления, если результат не используется.
map
просто создаёт ленивое представление списка. print
вызывает show
, но show
на списках вызывает show
только на нужных элементах при необходимости.В результате,
traceShow
может сработать один раз или вообще не выполниться, если не происходит полного прохода по списку.---
✅ Пример вывода:
1
[2,4,6,8,10]
Хоть в
map
был traceShow
, только первый элемент срабатывает (или вообще никто — в зависимости от версии).---
✅ Правильный способ — форсировать вычисление:
```haskell
import Debug.Trace
import Control.DeepSeq
main :: IO ()
main = do
let xs = [1..5]
let ys = map (\x -> traceShow x (x * 2)) xs
ys `deepseq` print ys
```
Теперь `traceShow` сработает **для каждого элемента**, потому что `deepseq` заставит Haskell **полностью вычислить список** перед `print`.
---
⚠️ Подвох
• `map` не вызывает функцию сразу — только когда элемент реально нужен
• `print` может не форсировать весь список
• Это вызывает недоумение у тех, кто ожидает «ленивость только в `IO`»
🎯 Отличная задача, чтобы проверить знание ленивости и управления побочными эффектами в Haskell.
BY Haskell
Share with your friend now:
tgoop.com/haskell_tg/36