blob: 49aecdcc7f6ed38f6c59544236510a55287f4012 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
module Main where
import Data.List
-- These four functions should all wind up the same; they represent successive
-- simplifications that should happen. (Actual details may vary, since find
-- isn't quite defined this way, but the differences disappear by the end.)
firstEvenIsPositive1 :: [Int] -> Bool
firstEvenIsPositive1 = maybe False (> 0) . find even
-- After inlining:
firstEvenIsPositive2 :: [Int] -> Bool
firstEvenIsPositive2 xs =
let go xs = case xs of x:xs' -> if even x then Just x else go xs'
[] -> Nothing
in case go xs of Just n -> n > 0
Nothing -> False
-- Note that go *could* be a join point if it were declared inside the scrutinee
-- instead of outside. So it's now Float In's job to move the binding inward a
-- smidge. *But* if it goes too far inward (as it would until recently), it will
-- wrap only "go" instead of "go xs", which won't let us mark go as a join point
-- since join points can't be partially invoked.
--
-- After Float In:
firstEvenIsPositive3 :: [Int] -> Bool
firstEvenIsPositive3 xs =
case let {-join-} go xs = case xs of x:xs' -> if even x then Just x
else go xs'
[] -> Nothing
in go xs of
Just n -> n > 0
Nothing -> False
-- After the simplifier:
firstEvenIsPositive4 :: [Int] -> Bool
firstEvenIsPositive4 xs =
let {-join-} go xs = case xs of x:xs' -> if even x then x > 0 else go xs'
[] -> False
in go xs
-- This only worked because go was a join point so that the case gets moved
-- inside.
{-# NOINLINE firstEvenIsPositive1 #-}
main = print $ or $ [firstEvenIsPositive1 [1,3..n] | n <- [1..10000]]
|