I would like to know what is the most standard way in Haskell.
The first one states clearly that we want two arguments (most of the time).
The second involves a function call (id) in the second clause, so it should be less efficient because in the first implementation we can simply return the second argument.
So i tend to think that the first is better and should be the one to pick : easier to read and to figure out what it does[1], and a function call save.
But i'm newbie to Haskell, maybe the compiler optimize this extra call.
xor :: Bool -> Bool -> Bool
xor True x = not x
xor False x = x
xor True = not
xor False = id
Also, i would like to know if i can replace both False with a wildcard there.
So, what is the good practice in Haskell. Maybe another implementation ?
[1] We omit there that it is a well known functionallity, let's imagine it is a non-trivial function.
Thanks
For readability, I would try to avoid pattern matching and define the function with a single equation that expresses something interesting about the function to be defined. That's not always possible, but for this example, there are many options:
xor = (/=)
xor a b = a /= b
xor a b = not (a == b)
xor a b = (a && not b) || (not a && b)
xor a b = (a || b) && not (a && b)
xor a b = odd (fromEnum a + fromEnum b)
Of course it depends on the compiler and the options passed to the compiler.
For this particular example, if you compile without optimisations, GHC produces the code as you have written it, so the second version contains a call to id resp. to not. That is slightly less efficient than the first version, which then only contains the call to not:
Xors.xor1 :: GHC.Types.Bool -> GHC.Types.Bool -> GHC.Types.Bool
[GblId, Arity=2]
Xors.xor1 =
\ (ds_dkm :: GHC.Types.Bool) (x_aeI :: GHC.Types.Bool) ->
case ds_dkm of _ {
GHC.Types.False -> x_aeI;
GHC.Types.True -> GHC.Classes.not x_aeI
}
Xors.xor2 :: GHC.Types.Bool -> GHC.Types.Bool -> GHC.Types.Bool
[GblId, Arity=1]
Xors.xor2 =
\ (ds_dki :: GHC.Types.Bool) ->
case ds_dki of _ {
GHC.Types.False -> GHC.Base.id # GHC.Types.Bool;
GHC.Types.True -> GHC.Classes.not
}
(the calls are still in the produced assembly, but core is more readable, so I post only that).
But with optimisations, both functions compile to the same core (and thence to the same machine code),
Xors.xor2 =
\ (ds_dkf :: GHC.Types.Bool) (eta_B1 :: GHC.Types.Bool) ->
case ds_dkf of _ {
GHC.Types.False -> eta_B1;
GHC.Types.True ->
case eta_B1 of _ {
GHC.Types.False -> GHC.Types.True;
GHC.Types.True -> GHC.Types.False
}
}
GHC eta-expanded the second version and inlined the calls to id and not, you get pure pattern-matching.
Whether the second equation uses False or a wildcard makes no difference in either version, with or without optimisations.
maybe the compiler optimize this extra call.
If you ask it to optimise, in simple cases like this, GHC will eliminate the extra call.
let's imagine it is a non-trivial function.
Here's a possible problem. If the code is non-trivial enough, the compiler may not be able to eliminate all calls introduced by defining the function with not all arguments supplied. GHC is rather good at doing that and inlining calls, though, so you need a fair amount of non-triviality to make GHC fail eliminating calls to simple functions it knows when compiling your code (it can of course never inline calls to functions it doesn't know the implementation of when compiling the module in question).
If it's critical code, always check what code the compiler produces, for GHC, the relevant flags are -ddump-simpl to get the core produced after optimisations, and -ddump-asm to get the produced assembly.
So i tend to think that the first is better and should be the one to pick : easier to read and to figure out what it does
I agree about readability. However, the second one is very much idiomatic Haskell and rather easier to read for experienced programmers: not performing that trivial eta reduction is quite suspicious and might actually distract from the intend. So for an optimised version, I'd rather write it out completely in explicit form:
True `xor` False = True
False `xor` True = True
_ `xor` _ = False
However, if such an alternative is considerably less readable than the most idiomatic one you should consider not replacing it, but adding hints so the compiler can still optimise it to the ideal version. As demonstrated by Daniel Fischer, GHC is quite clever by itself and will often get it right without help; when it doesn't it might help to add some INLINE and/or RULES pragmas. It's not easy to figure out how to do this to get optimal performance, but the same is true for writing fast Haskell98 code.
Related
To me it seems that you can always pass function arguments rather than using a typeclass. For example rather than defining equality typeclass:
class Eq a where
(==) :: a -> a -> Bool
And using it in other functions to indicate type argument must be an instance of Eq:
elem :: (Eq a) => a -> [a] -> Bool
Can't we just define our elem function without using a typeclass and instead pass a function argument that does the job?
Yes. This is called "dictionary passing style". Sometimes when I am doing some especially tricky things, I need to scrap a typeclass and turn it into a dictionary, because dictionary passing is more powerful1, yet often quite cumbersome, making conceptually simple code look quite complicated. I use dictionary passing style sometimes in languages that aren't Haskell to simulate typeclasses (but have learned that that is usually not as great an idea as it sounds).
Of course, whenever there is a difference in expressive power, there is a trade-off. While you can use a given API in more ways if it is written using DPS, the API gets more information if you can't. One way this shows up in practice is in Data.Set, which relies on the fact that there is only one Ord dictionary per type. The Set stores its elements sorted according to Ord, and if you build a set with one dictionary, and then inserted an element using a different one, as would be possible with DPS, you could break Set's invariant and cause it to crash. This uniqueness problem can be mitigated using a phantom existential type to mark the dictionary, but, again, at the cost of quite a bit of annoying complexity in the API. This also shows up in pretty much the same way in the Typeable API.
The uniqueness bit doesn't come up very often. What typeclasses are great at is writing code for you. For example,
catProcs :: (i -> Maybe String) -> (i -> Maybe String) -> (i -> Maybe String)
catProcs f g = f <> g
which takes two "processors" which take an input and might give an output, and concatenates them, flattening away Nothing, would have to be written in DPS something like this:
catProcs f g = (<>) (funcSemi (maybeSemi listSemi)) f g
We essentially had to spell out the type we're using it at again, even though we already spelled it out in the type signature, and even that was redundant because the compiler already knows all the types. Because there's only one way to construct a given Semigroup at a type, the compiler can do it for you. This has a "compound interest" type effect when you start defining a lot of parametric instances and using the structure of your types to compute for you, as in the Data.Functor.* combinators, and this is used to great effect with deriving via where you can essentially get all the "standard" algebraic structure of your type written for you.
And don't even get me started on MPTC's and fundeps, which feed information back into typechecking and inference. I have never tried converting such a thing to DPS -- I suspect it would involve passing around a lot of type equality proofs -- but in any case I'm sure it would be a lot more work for my brain than I would be comfortable with.
--
1Unless you use reflection in which case they become equivalent in power -- but reflection can also be cumbersome to use.
Yes. That (called dictionary passing) is basically what the compiler does to typeclasses anyway. For that function, done literally, it would look a bit like this:
elemBy :: (a -> a -> Bool) -> a -> [a] -> Bool
elemBy _ _ [] = False
elemBy eq x (y:ys) = eq x y || elemBy eq x ys
Calling elemBy (==) x xs is now equivalent to elem x xs. And in this specific case, you can go a step further: eq has the same first argument every time, so you can make it the caller's responsibility to apply that, and end up with this:
elemBy2 :: (a -> Bool) -> [a] -> Bool
elemBy2 _ [] = False
elemBy2 eqx (y:ys) = eqx y || elemBy2 eqx ys
Calling elemBy2 (x ==) xs is now equivalent to elem x xs.
...Oh wait. That's just any. (And in fact, in the standard library, elem = any . (==).)
Let's say I pass a small function f to map. Can Haskell inline f with map to produce a small imperative loop? If so, how does Haskell keep track of what function f really is? Can the same be done with Arrow combinators?
If f is passed in as an argument, then no, probably not. If f is the name of a top-level function or a local function, then probably yes.
foobar f = ... map f ...
-- Probably not inlined.
foobar = ... map (\ x -> ...) ...
-- Probably inlined.
That said, I gather that most of the performance difference between inline and out of line comes not from the actual inlining itself, but rather from any additional subsequent optimisations this might allow.
The only way to be "sure" about these things is to actually write the code, actually compile it, and have a look at the Core that gets generated. And the only way to know if it makes a difference (positive or negative) is to actually benchmark the thing.
The definition of the Haskell language does not mandate a Haskell implementation to inline code, or to perform any kind of optimization. Any implementation is free to apply any optimization it may deem appropriate.
That being said, Haskell is nowadays often run using GHC, which does optimize Haskell code. For inlining, GHC uses some heuristics to decide whether something should inlined or not. The general advice is to turn optimization on with -O2 and check the output of the compiler. You can see the produced Core with -ddump-simpl, or the assembly code with -ddump-asm. Some other flags can be useful as well.
If you then see that GHC is not inlining stuff you would like to, you can provide a hint to the compiler with {-# INLINE foo #-} and related pragmas.
Be wary of mindlessly applying optimizations, though. Often, programmers spend their time to optimize parts of the program which have a negligible impact to the overall performance. To avoid this, it is strongly recommended to profile your code first, so that you know where your program spends a lot of time.
Here is an example where GHC does inline a function passed as an argument :
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector as V
plus :: Int -> Int -> Int
plus = (+)
sumVect :: V.Vector Int -> Int
sumVect = V.foldl1 plus
plus is passed as the argument of foldl1, which results in summing a vector of integers. In the Core, plus is inlined and optimized to the unboxed GHC.Prim.+# :: Int# -> Int# -> Int# :
letrec {
$s$wfoldlM_loop_s759
:: GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Prim.Int#
$s$wfoldlM_loop_s759 =
\ (sc_s758 :: GHC.Prim.Int#) (sc1_s757 :: GHC.Prim.Int#) ->
case GHC.Prim.tagToEnum# # Bool (GHC.Prim.>=# sc_s758 ww1_s748)
of _ {
False ->
case GHC.Prim.indexArray#
# Int ww2_s749 (GHC.Prim.+# ww_s747 sc_s758)
of _ { (# ipv1_X72o #) ->
case ipv1_X72o of _ { GHC.Types.I# y_a5Kg ->
$s$wfoldlM_loop_s759
(GHC.Prim.+# sc_s758 1#) (GHC.Prim.+# sc1_s757 y_a5Kg)
}
};
True -> sc1_s757
}; }
That's the GHC.Prim.+# sc1_s757 y_a5Kg. You can add simple artihmetic inside function plus and see this Core expression expand.
According to this article,
Enumerations don't count as single-constructor types as far as GHC is concerned, so they don't benefit from unpacking when used as strict constructor fields, or strict function arguments. This is a deficiency in GHC, but it can be worked around.
And instead the use of newtypes is recommended. However, I cannot verify this with the following code:
{-# LANGUAGE MagicHash,BangPatterns #-}
{-# OPTIONS_GHC -O2 -funbox-strict-fields -rtsopts -fllvm -optlc --x86-asm-syntax=intel #-}
module Main(main,f,g)
where
import GHC.Base
import Criterion.Main
data D = A | B | C
newtype E = E Int deriving(Eq)
f :: D -> Int#
f z | z `seq` False = 3422#
f z = case z of
A -> 1234#
B -> 5678#
C -> 9012#
g :: E -> Int#
g z | z `seq` False = 7432#
g z = case z of
(E 0) -> 2345#
(E 1) -> 6789#
(E 2) -> 3535#
f' x = I# (f x)
g' x = I# (g x)
main :: IO ()
main = defaultMain [ bench "f" (whnf f' A)
, bench "g" (whnf g' (E 0))
]
Looking at the assembly, the tags for each constructor of the enumeration D is actually unpacked and directly hard-coded in the instruction. Furthermore, the function f lacks error-handling code, and more than 10% faster than g. In a more realistic case I have also experienced a slowdown after converting a enumeration to a newtype. Can anyone give me some insight about this? Thanks.
It depends on the use case. For the functions you have, it's expected that the enumeration performs better. Basically, the three constructors of D become Ints resp. Int#s when the strictness analysis allows that, and GHC knows it's statically checked that the argument can only have one of the three values 0#, 1#, 2#, so it needs not insert error handling code for f. For E, the static guarantee of only one of three values being possible isn't given, so it needs to add error handling code for g, that slows things down significantly. If you change the definition of g so that the last case becomes
E _ -> 3535#
the difference vanishes completely or almost completely (I get a 1% - 2% better benchmark for f still, but I haven't done enough testing to be sure whether that's a real difference or an artifact of benchmarking).
But this is not the use case the wiki page is talking about. What it's talking about is unpacking the constructors into other constructors when the type is a component of other data, e.g.
data FooD = FD !D !D !D
data FooE = FE !E !E !E
Then, if compiled with -funbox-strict-fields, the three Int#s can be unpacked into the constructor of FooE, so you'd basically get the equivalent of
struct FooE {
long x, y, z;
};
while the fields of FooD have the multi-constructor type D and cannot be unpacked into the constructor FD(1), so that would basically give you
struct FooD {
long *px, *py, *pz;
}
That can obviously have significant impact.
I'm not sure about the case of single-constructor function arguments. That has obvious advantages for types with contained data, like tuples, but I don't see how that would apply to plain enumerations, where you just have a case and splitting off a worker and a wrapper makes no sense (to me).
Anyway, the worker/wrapper transformation isn't so much a single-constructor thing, constructor specialisation can give the same benefit to types with few constructors. (For how many constructors specialisations would be created depends on the value of -fspec-constr-count.)
(1) That might have changed, but I doubt it. I haven't checked it though, so it's possible the page is out of date.
I would guess that GHC has changed quite a bit since that page was last updated in 2008. Also, you're using the LLVM backend, so that's likely to have some effect on performance as well. GHC can (and will, since you've used -O2) strip any error handling code from f, because it knows statically that f is total. The same cannot be said for g. I would guess that it's the LLVM backend that then unpacks the constructor tags in f, because it can easily see that there is nothing else used by the branching condition. I'm not sure of that, though.
Real World Haskell has this example:
class BasicEq3 a where
isEqual3 :: a -> a -> Bool
isEqual3 x y = not (isNotEqual3 x y)
isNotEqual3 :: a -> a -> Bool
isNotEqual3 x y = not (isEqual3 x y)
instance BasicEq3 Bool
And when I run it in GHCI:
#> isEqual3 False False
out of memory
So, you have to implement at least one of the 2 methods or it will loop. And you get the flexibility of choosing which one, which is neat.
The question I have is, is there a way to get a warning or something if didn't override enough of the defaults and the defaults form a loop? It seems strange to me that the compiler that is so crazy smart is fine with this example.
I think it's perfectly fine for GHC to issue a warning in case of an "unbroken" cyclic dependency. There's even a ticket along those lines: http://hackage.haskell.org/trac/ghc/ticket/6028
Just because something is "undecidable" doesn't mean no instance of the problem can be solved effectively. GHC (or any other Haskell compiler) already has quite a bit of the information it needs, and it'd be perfectly possible for it to issue a warning if the user is instantiating a class without "breaking" the cyclic dependency. And if the compiler gets it wrong in the rare cases as exemplified in previous posts, then the user can have a -nowarnundefinedcyclicmethods or a similar mechanism to tell GHC to be quiet. In nearly every other case, the warning will be most welcome and would add to programmer productivity; avoiding what's almost always a silly bug.
No, I'm afraid GHC doesn't do anything like that. Also that isn't possible in general.
You see, the methods of a type class could be mutually recursive in a useful way. Here's a contrived example of such a type class. It's perfectly fine to not define either sumOdds or sumEvens, even though their default implementations are in terms of each other.
class Weird a where
measure :: a -> Int
sumOdds :: [a] -> Int
sumOdds [] = 0
sumOdds (_:xs) = sumEvens xs
sumEvens :: [a] -> Int
sumEvens [] = 0
sumEvens (x:xs) = measure x + sumOdds xs
No, there isn't, since if the compiler could make this determination, that would be equivalent to solving the Halting Problem. In general, the fact that two functions call each other in a "loop" pattern is not enough to conclude that actually calling one of the functions will result in a loop.
To use a (contrived) example,
collatzOdd :: Int -> Int
collatzOdd 1 = 1
collatzOdd n = let n' = 3*n+1 in if n' `mod` 2 == 0 then collatzEven n'
else collatzOdd n'
collatzEven :: Int -> Int
collatzEven n = let n' = n `div` 2 in if n' `mod` 2 == 0 then collatzEven n'
else collatzOdd n'
collatz :: Int -> Int
collatz n = if n `mod` 2 == 0 then collatzEven n else collatzOdd n
(This is of course not the most natural way to implement the Collatz conjecture, but it illustrates mutually recursive functions.)
Now collatzEven and collatzOdd depend on each other, but the Collatz conjecture states that calling collatz terminates for all positive n. If GHC could determine whether a class that had collatzOdd and collatzEven as default definitions had a complete definition or not, then GHC would be able to solve the Collatz conjecture! (This is of course not a proof of the undecideability of the Halting Problem, but it should illustrate why determining whether a mutually recursive set of functions is well-defined is not at all as trivial as it may seem.)
In general, since GHC cannot determine this automatically, documentation for Haskell classes will give the "minimal complete definition" necessary for creating an instance of a class.
I don't think so. I worry that you're expecting the compiler to solve the halting problem! Just because two functions are defined in terms of each other, doesn't mean it's a bad default class. Also, I've used classes in the past where I just needed to write instance MyClass MyType to add useful functionality. So asking the compiler to warn you about that class is asking it to complain about other, valid code.
[Of course, use ghci during development and test every function after you've written it!
Use HUnit and/or QuickCheck, just to make sure none of this stuff ends up in final code.]
In my personal opinion, the defaulting mechanism is unnecessary and unwise. It would be easy for the class author to just provide the defaults as ordinary functions:
notEq3FromEq3 :: (a -> a -> Bool) -> (a -> a -> Bool)
notEq3FromEq3 eq3 = (\x y -> not (eq3 x y))
eq3FromNotEq3 :: (a -> a -> Bool) -> (a -> a -> Bool)
eq3FromNotEq3 ne3 = (\x y -> not (ne3 x y))
(In fact, these two definitions are equal, but that would not be true in general). Then an instance looks like:
instance BasicEq3 Bool where
isEqual3 True True = True
isEqual3 False False = True
isEqual3 _ _ = False
isNotEqual3 = notEq3FromEq3 isEqual3
and no defaults are required. Then GHC can warn you if you don't provide the definition, and any unpleasant loops have to be explicitly written by you into your code.
This does remove the neat ability to add new methods to a class with default definitions without affecting existing instances, but that's not so huge a benefit in my view. The above approach is also in principle more flexible: you could e.g. provide functions that allowed an Ord instance to choose any comparison operator to implement.
Is there a GHC-specific "unsafe" extension to ask whether two Haskell references point to the same location?
I'm aware this can break referential transparency if not used properly. But there should be little harm (unless I'm missing something), if it is used very careful, as a means for optimizations by short-cutting recursive (or expensive) data traversal, e.g. for implementing an optimized Eq instance, e.g.:
instance Eq ComplexTree where
a == b = (a `unsafeSameRef` b) || (a `deepCompare` b)
providing deepCompare is guaranteed to be true if unsafeSameRef decides true (but not necessarily the other way around).
EDIT/PS: Thanks to the answer pointing to System.Mem.StableName, I was able to also find the paper Stretching the storage manager: weak pointers and stable names in Haskell which happens to have addressed this very problem already over 10 years ago...
GHC's System.Mem.StableName solves exactly this problem.
There's a pitfall to be aware of:
Pointer equality can change strictness. I.e., you might get pointer equality saying True when in fact the real equality test would have looped because of, e.g., a circular structure. So pointer equality ruins the semantics (but you knew that).
I think StablePointers might be of help here
http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/Foreign-StablePtr.html
Perhaps this is the kind of solution you are looking for:
import Foreign.StablePtr (newStablePtr, freeStablePtr)
import System.IO.Unsafe (unsafePerformIO)
unsafeSameRef :: a -> a -> Bool
unsafeSameRef x y = unsafePerformIO $ do
a <- newStablePtr x
b <- newStablePtr y
let z = a == b
freeStablePtr a
freeStablePtr b
return z;
There's unpackClosure# in GHC.Prim, with the following type:
unpackClosure# :: a -> (# Addr#,Array# b,ByteArray# #)
Using that you could whip up something like:
{-# LANGUAGE MagicHash, UnboxedTuples #-}
import GHC.Prim
eq a b = case unpackClosure# a of
(# a1,a2,a3 #) -> case unpackClosure# b of
(# b1,b2,b3 #) -> eqAddr# a1 b1
And in the same package, there's the interestingly named reallyUnsafePtrEquality# of type
reallyUnsafePtrEquality# :: a -> a -> Int#
But I'm not sure what the return value of that one is - going by the name it will lead to much gnashing of teeth.