morloc
morloc copied to clipboard
Cannot force order of operations
Suppose we have a sampleBy
function that selects items from a list of pairs based on the second element value and then returns the selected first values. It takes a function of all the second values and returns their indices in the original list. This can be implemented as below:
sampleBy :: ([b] -> [Int]) -> [(a, b)] -> [a]
sampleBy f xs = map (at (map fst xs)) (f (map snd xs))
Where
-- lookup a value in a vector by index
at :: [a] -> Int -> a
fst :: (a, b) -> a
snd :: (a, b) -> b
map :: (a -> b) -> [a] -> [b]
The sampleBy
implementation looks nice, however, when the code is generated, the map fst xs
expression is re-evaluated at every index lookup. I want to force it to be evaluated only once. I can rewrite the expression as:
sampleBy f xs = map (at labels) (f (map snd xs)) where
labels = map fst xs
But this evaluates to exactly the same code again, with labels
being substituted into the main expression.
What would be nice is a means to force order of evaluation. Perhaps with let
syntax?
sampleBy f xs =
let labels = map fst xs
let data = map snd xs
map (at labels) (f data)
Where the compiler guarantees labels
will be evaluated just once before the main expression. Adding let
is a pretty major change.
Alternatively, we could define let
as a source functions that forces evaluation:
let :: a -> (a -> b) -> b
This approach may serve as workaround until we implement real let
handling.