Фон
Этот вопрос возникает из задачи, которую Брент Йорги поставил на OPLSS: напишите функцию f :: (Int -> Int) -> Bool
, которая отличает f undefined
от f (\x -> undefined)
.Во всех наших ответах использовались либо seq
, либо что-то вроде паттернов взрыва, которые вводятся в seq
.Например:
f :: (Int -> Int) -> Bool
f g = g `seq` True
*Main> f undefined
*** Exception: Prelude.undefined
*Main> f (\x -> undefined)
True
В комментарии GHC к seq
говорится, что
e1 `seq` e2
используется для десугарации в
case e1 of { _ -> e2 }
, поэтомуЯ попытался desugaring вручную.Это не сработало:
f' g = case g of { _ -> True }
*Main> f' undefined
True
*Main> f' (\x -> undefined)
True
Вопрос
Зависит ли это поведение от более сложного seq
, описанного в конце комментария , и если да, то, как это работает?Может ли такой f
быть написан без этих примитивов?
x `seq` e2 ==> case seq# x RW of (# x, _ #) -> e2 -- Note shadowing!
e1 `seq` e2 ==> case seq# x RW of (# _, _ #) -> e2