I'm reading this blog post by Michael Snoyman recently. In an exercise suggested there, I tried to define $!
operator by myself:
import Prelude hiding ( ($!) )
($!) :: (a -> b) -> a -> b
($!) f x = x `seq` f x
mysum :: [Int] -> Int
mysum list0 =
go list0 0
where
go [] total = total
go (x:xs) total = go xs $! total + x
main = print $ mysum [1..1000000]
I thought this works well, though the usage of memory was terrible. My first question is this. Why didn't this work well?
Then, I checked its definition in Prelude. It reads:
($!) :: (a -> b) -> a -> b
f $! x = let !vx = x in f vx -- see #2273
So, I copied it into my code:
{-# LANGUAGE BangPatterns #-}
import Prelude hiding ( ($!) )
($!) :: (a -> b) -> a -> b
($!) f x =
let !vx = x
in f vx
mysum :: [Int] -> Int
mysum list0 =
go list0 0
where
go [] total = total
go (x:xs) total = go xs $! total + x
main = print $ mysum [1..1000000]
and the result was:
Linking mysum4 ...
500000500000
209,344,064 bytes allocated in the heap
130,602,696 bytes copied during GC
54,339,936 bytes maximum residency (8 sample(s))
66,624 bytes maximum slop
80 MB total memory in use (0 MB lost due to fragmentation)
You can see how terrible this is compared to the result of using Prelude's $!
operator:
Linking mysum4 ...
500000500000
152,051,776 bytes allocated in the heap
41,752 bytes copied during GC
44,384 bytes maximum residency (2 sample(s))
21,152 bytes maximum slop
1 MB total memory in use (0 MB lost due to fragmentation)
My second question is where did this difference come from?
Furthermore, I think it can be re-written like this:
($!) :: (a -> b) -> a -> b
f $! !x = f x
Is there any reason not to do this? This is my third question.
Personal Biases: The way a supervisor feels about each of the individuals working under him - whether he likes or dislikes them - as a tremendous effect on the rating of their performances.
Being able to manage yourself and your own performance is an attribute that employers look for as employees who are well organised, understand their role and are always looking to increase their skills and knowledge through research, training or other means are likely to have a positive effect on their organisation.
Aha! It's a precedence issue. You forgot to paste the line:
infixr 0 $!
and so when you use your own version, it gets parsed as
go (x:xs) total = (go xs $! total) + x
which obviously has terrible performance. It's almost a coincidence that it even gives you the right answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With