I read this:
http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns
I like the idea, want to use the extension. I however would like to make sure as to one thing: whether the view function is evaluated once for a single matching.
So let's say we have:
{-# LANGUAGE ViewPatterns #-}
...
f (view -> Nothing) = ...
f (view -> Just x) = ...
view :: a -> Maybe b
Now let's say I invoke f a
. Is view
invoked twice or just once for the given argument a
?
EDIT:
I tried to find out whether this is the case and wrote the following:
{-# LANGUAGE ViewPatterns #-}
import System.IO.Unsafe
blah (ble -> Nothing) = 123
blah (ble -> Just x) = x
ble x = unsafePerformIO $ do
putStrLn $ "Inside ble: " ++ show x
return x
main :: IO ()
main = do
putStrLn $ "Main: " ++ show (blah $ Just 234)
Output using GHC:
Inside ble: Just 234
Inside ble: Just 234
Main: 234
Output using GHC (with optimization)
Inside ble: Just 234
Main: 234
Output using GHCi:
Main: Inside ble: Just 234
Inside ble: Just 234
234
Just once:
Efficiency: When the same view function is applied in multiple branches of a function definition or a case expression (e.g., in
size
above), GHC makes an attempt to collect these applications into a single nested case expression, so that the view function is only applied once. Pattern compilation in GHC follows the matrix algorithm described in Chapter 4 of The Implementation of Functional Programming Languages. When the top rows of the first column of a matrix are all view patterns with the "same" expression, these patterns are transformed into a single nested case. This includes, for example, adjacent view patterns that line up in a tuple, as inf ((view -> A, p1), p2) = e1 f ((view -> B, p3), p4) = e2The current notion of when two view pattern expressions are "the same" is very restricted: it is not even full syntactic equality. However, it does include variables, literals, applications, and tuples; e.g., two instances of
view ("hi", "there")
will be collected. However, the current implementation does not compare up to alpha-equivalence, so two instances of(x, view x -> y)
will not be coalesced.— The GHC manual
As for your snippet, the problem is that you're not compiling with optimisation; with both ghc -O
and ghc -O2
, the line is only printed once. That's always the first thing to check when you have performance-related problems when using GHC :)
(By the way, Debug.Trace lets you check these kinds of things without having to write manual unsafePerformIO
hacks.)
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