Фон
Этот вопрос возникает из-за того, что Брент Йорги поставил на OPLSS: напишите функцию f :: (Int -> Int) -> Bool
, которая отличает f undefined
от f (\x -> undefined)
. Все наши ответы либо использовали seq
, либо что-то вроде шаблонов ударов, которые desugar в 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