Use GHC 8.4.1 (or later)
With the Semigroup Monoid Proposal and the release of GHC 8.4.1, Semigroup
has been moved to the Prelude
. This gives us:
(<>) :: Semigroup a => a -> a -> a
Now these might seem useless at first glance, but looking closer we notice that Monoid a => (x -> a)
is an instance of Monoid
1, in which case we have the implementation:
(f <> g) xs = f xs <> g xs
This can be quite useful with for example lists, knowing that (<>)
is the same as (++)
for lists. So we have for example:
(init <> reverse) [1,2,3] ≡ init [1,2,3] <> reverse [1,2,3]
≡ [1,2] <> [3,2,1]
≡ [1,2] ++ [3,2,1]
≡ [1,2,3,2,1]
However, this is not the only useful case: Knowing that [x] -> [x]
is an instance of Monoid
, we also have a -> [x] -> [x]
an instance of Monoid
(you can iterate this as many times as you want):
(drop <> take) 2 [1,2,3,4,5] ≡ (drop 2 <> take 2) [1,2,3,4,5]
≡ drop 2 [1,2,3,4,5] <> take 2 [1,2,3,4,5]
≡ [3,4,5] <> [1,2]
≡ [3,4,5,1,2]
1: Note that Monoid a
\$\implies\$ Semigroup a
.
Overview what we gained so far
Using this trick we have these (not exhaustive) helpers, note that we can chain them:
duplicate = id <> id
triple² = id <> id <> id
palindromize = init <> reverse
rotateLeft = drop <> take
removeElementAt = take <> drop . succ
removeNElementsAt n = take <> drop . (+n)
2: This could also be ([1..3]>>)
for the same bytecount be shorter (see comment by Ørjan Johansen).
Where are the \$(\mathbb{Z},\texttt{+})\$ and \$(\mathbb{Z},\texttt{*})\$ monoids?
If we want to use the \$(\mathbb{Z},\texttt{+})\$ monoid, we need to tell GHC that. It can not decide for us which one it should use, therefore there are two newtype
s which allow this - Sum
and Product
.
Given that the consensus is to allow implicitly typed functions, we are probably allowed to do so if the challenge does not talk about a specific implementation for integers. Using this we can for example write \$n\$th oblong number as
id<>(+1)
which is shorter than f n=n*(n-1)
or even (*)=<<succ
/(*)<*>succ
.
Try it online!3
3: Note that we need to use (+1)
and cannot use succ
since GHC can't know that there is an instance of Enum
.
Other noteworthy related tricks
Instances that might be useful not covered above:
()
Ordering
(Monoid a, Monoid b) => Monoid (a,b) -- (also 3-,4- and 5-tuples)
Monoid a => Monoid (IO a)
Ord k => Monoid (Map k v) -- from Data.Map
It might be worth noting that there is mconcat
too:
mconcat [f1,f2,…,fN] ≡ f1 <> f2 <> … <> fN
This will probably not be useful often, for it needs at least \$3-11\$ functions (depending on the need of parentheses, see comments), but it might be in case you have some list Monoid a => [a]
already.
Furthermore mempty
can be useful since it is shorter than Nothing
or even pure Nothing
, ([],[])
etc.
Another useful instance is Monoid a => Monoid (IO a)
which has successfully been used for the currently shortest quine as
(putStr <> print) "foo" ≡ putStr "foo" <> print "foo"
≡ do x <- putStr "foo"
y <- print "foo"
pure $ x <> y
≡ do putStr "foo"
print "foo"
pure ()
≡ putStr "foo" >> print "foo"
3Special request, String compression. – J Atkin – 2016-02-20T00:07:05.330
This is probably not suited as an anwer, but I'm still want to add it here: https://wiki.haskell.org/Prime_numbers_miscellaneous#One-liners
– flawr – 2016-05-25T19:38:15.770Another (rather funny, but still interesting) one: http://www.willamette.edu/~fruehr/haskell/evolution.html
– flawr – 2016-06-11T09:09:31.430Also another link: https://wiki.haskell.org/Blow_your_mind
– flawr – 2016-07-30T19:16:37.6831Seeing the number of answers till now, I am in doubt about whether Haskell is even a good language for code golfing or not? – Animesh 'the CODER' – 2014-01-24T10:23:45.417
10Why only one tip per answer? Also, every language is a good language for golfing. Just don't always expect to win. – unclemeat – 2014-02-12T00:46:36.467
6@unclemeat This way people could upvote the good ones to the top without upvoting the bad ones only because they were written by the same guy in the same answer. – MasterMastic – 2014-06-01T12:10:54.733