I have a trivial example of an SQL-like join for ordered lists: if outer is True , then it is concatenated; otherwise this intersection:
import System.Environment main = do [arg] <- getArgs let outer = arg == "outer" print $ length $ joinLists outer [1..1000] [1,3..1000] joinLists :: (Ord a, Num a) => Bool -> [a] -> [a] -> [a] joinLists outer xs ys = go xs ys where go [] _ = [] go _ [] = [] go xs@ (x:xs') ys@ (y:ys') = case compare xy of LT -> append x $ go xs' ys GT -> append y $ go xs ys' EQ -> x : go xs' ys' append k = if {-
When I look at it, I see that the isOuter condition is evaluated every time append is called:
stack ghc -- -O2 -prof example.hs && ./example outer +RTS -p && cat example.prof individual inherited COST CENTRE MODULE no. entries %time %alloc %time %alloc MAIN MAIN 44 0 0.0 34.6 0.0 100.0 isOuter Main 88 499 0.0 0.0 0.0 0.0
But I would like the condition to be evaluated only once, so the append in the go loop is replaced with either (k :) or id . Can I make him somehow? Is this related to memoization?
EDIT: Looks like I misinterpreted the profiler output. I added tracing to the append definition:
append k = if trace "outer" outer then (k :) else id
And outer is printed only once.
EDIT2: If I replaced append with a append definition, then the if condition is evaluated only once:
append = if outer then (:) else flip const
optimization haskell
modular
source share