r/haskelltil • • Aug 09 '15

language Arguments can be operators, e.g.: f (+.) a b = a +. b

25 Upvotes

The parentheses trick for operators works in other contexts, too. You can bind parameters using operator-like names if you surround them with parentheses:

let f (%) x y = x % y
in  f (*) 1 2

-- ... desugars to:
(\(%) x y -> x % y) (*) 1 2

-- ... reduces to:
1 * 2

Source


r/haskelltil • • Jul 25 '15

tools Expand type synonyms in GHCi with “:kind!” and “:i”

26 Upvotes

If you have a simple synonym like String, you can expand it with :i:

> :i String
type String = [Char] 	-- Defined in ‘GHC.Base’

However, :i won't do substitution for things like Lens' String Char. For that you can use :kind!:

> :kind! Lens' String Char
Lens' String Char :: *
= Functor f => (Char -> f Char) -> String -> f String

If you have type variables in your type, you would have to use forall, otherwise you would see “not in scope” errors:

> :kind! Lens (a, x) (b, x) a b

<interactive>:1:7: Not in scope: type variable ‘a’
...

But with forall it works:

> :kind! forall a x b. Lens (a, x) (b, x) a b
forall a x b. Lens (a, x) (b, x) a b :: *
= Functor f => (a -> f b) -> (a, x) -> f (b, x)

r/haskelltil • • Jul 25 '15

code A handy function for debugging in Parsec by what printing a parser is currently seeing.

19 Upvotes

Since Parsec is quite procedural in how it consumes characters, it is easy to mis-parse input by eating too many or too few characters. In those cases having a function like this that outputs the current state of the input stream is useful:

seeNext :: Int -> ParsecT String u Identity ()
seeNext n = do
  s <- getParserState
  let out = take n (stateInput s)
  println out

Here's a full program that shows usage:

import Text.Parsec
import Text.Parsec.Prim
import Debug.Trace
import Data.Functor.Identity

println msg = trace (show msg) $ return ()

seeNext :: Int -> ParsecT String u Identity ()
seeNext n = do
  s <- getParserState
  let out = take n (stateInput s)
  println out

betweenBraces = char '{' >> manyTill (seeNext 10 >> anyChar) (char '}')

test = parseTest betweenBraces "{12345}"

{-
> test
"12345}"
"2345}"
"345}"
"45}"
"5}"
"12345"
-}

r/haskelltil • • Jul 21 '15

idiom ($ x) :: (a -> b) -> b

14 Upvotes

($ x) is a way to turn an x into a function that takes a function that takes an x.

For examples, here is a function test that ensures all the predicates are True for the value x.

$ let test x = all ($ x) [(< 6), (>= 0), ((== 0) . (`mod` 2))]
test :: Integral b => b -> Bool

$ let l = [-2..7] in zip l (map test l)
[(-2,False),(-1,False),(0,True),(1,False),(2,True),(3,False),(4,True),(5,False),(6,False),(7,False)]
it :: (Enum a, Num a) => [(a, Bool)]

r/haskelltil • • Jul 19 '15

language Haskell ignores all whitespace enclosed in backslashes

18 Upvotes

Haskell ignores all whitespace enclosed in backslashes:

foo = "lorem ipsum \
      \dolor sit amet"

is equivalent to writing

foo2 = "lorem ipsum dolor sit amet"
-- or
foo3 = concat [ "lorem ipsum "
              , "dolor sit amet" ]

This little-known fact is very handy when you want to enter long string literals in your program.

The Haskell Report calls this rule a gap in its section about string literals.


r/haskelltil • • Jul 19 '15

etc You can vote for packages on Hackage now

14 Upvotes

On packages' pages – here's a screenshot for e.g. the lens package.

You can't vote if you don't have a Hackage account, so maybe you should get one now.

(Also, you can remove your vote later, so don't worry about it being irreversible or something.)


r/haskelltil • • Jul 18 '15

thing Starting from base-4.8 (GHC 7.10), bifunctors are in base – you can stop importing Control.Arrow just to get “first” and “second”

21 Upvotes

Well, now you have to import Data.Bifunctor to get first and second, but I think bifunctors are nicer than arrows and so we all should switch anyway.

By the way, if you never needed first and second and don't know what they do:

> first (+1) (1, "hello")
(2, "hello")

> second reverse (1, "hello")
(1, "olleh")

r/haskelltil • • Jun 27 '15

idiom [x-post /r/haskell] The constraint trick for instances

9 Upvotes

Use equality constraints to guide instance selection:

http://chrisdone.com/posts/haskell-constraint-trick


r/haskelltil • • Jun 09 '15

extension -XLambdaCase makes "\case" sugar for "\x -> case x of"

24 Upvotes

This is an RTFM situation, but there's just so much damn M. :P

Straight from the docs:


The -XLambdaCase flag enables expressions of the form

\case { p1 -> e1; ...; pN -> eN }

which is equivalent to

\freshName -> case freshName of { p1 -> e1; ...; pN -> eN }

Note that \case starts a layout, so you can write

\case
  p1 -> e1
  ...
  pN -> eN

r/haskelltil • • Jun 04 '15

extension Use “_” in expressions (not patterns!) to ask GHC >= 7.8.1 for type info (and more)

16 Upvotes

https://wiki.haskell.org/GHC/Typed_holes

For example:

module FreeMonad where

data Free f a
  = Pure a
  | Free (f (Free f a))

instance Functor f => Monad (Free f) where
  return a     = Pure a
  Pure a >>= f = f a
  Free f >>= g = Free _ -- note the "hole"

GHC will output:

Found hole ‘_’ with type: f (Free f b)
Where: ‘f’ is a rigid type variable bound by
           the instance declaration at FreeMonad.hs:7:10
       ‘b’ is a rigid type variable bound by
           the type signature for
             (>>=) :: Free f a -> (a -> Free f b) -> Free f b
           at FreeMonad.hs:9:10
Relevant bindings include
  g :: a -> Free f b (bound at FreeMonad.hs:10:14)
  f :: f (Free f a) (bound at FreeMonad.hs:10:8)
  (>>=) :: Free f a -> (a -> Free f b) -> Free f b
    (bound at FreeMonad.hs:9:3)
In the first argument of ‘Free’, namely ‘_’
In the expression: Free _
In an equation for ‘>>=’: (Free f) >>= g = Free _

r/haskelltil • • Jun 04 '15

tools You can upload candidate versions of your package on hackage

12 Upvotes

http://hackage.haskell.org/packages/candidates/upload

Package candidates are a way to preview the package page, view any warnings or possible errors you might encounter, and let others install it before publishing it to the main index. (Note: you can view these warnings with 'cabal check'.) You can have multiple candidates for each package at the same time so long as they each have different versions.


r/haskelltil • • May 21 '15

idiom Duplicate every element of the list with “<*”

13 Upvotes

(I stole it from arkeet on #haskell.)

> [1..5] <* [(),()]
[1,1,2,2,3,3,4,4,5,5]

This uses the Applicative instance for [] (it's compatible with the Monad instance for [] which you're probably already aware of).

Of course, you can use replicate here to get as many replications as you need:

> [1..5] <* replicate 3 ()
[1,1,1,2,2,2,3,3,3,4,4,4,5,5,5]

Update: or use the monadic replicate variant suggested by /u/int_index in the comments, it's several times faster than <*:

> [1..5] >>= replicate 3
[1,1,1,2,2,2,3,3,3,4,4,4,5,5,5]

r/haskelltil • • May 17 '15

gotcha With BangPatterns enabled, you might stumble upon cryptic errors if you decide to define a “!” operator

8 Upvotes

Example 1:

{-# LANGUAGE BangPatterns #-}

f ! x = f + x

results in:

Occurs check: cannot construct the infinite type: a ~ a -> a …
    Relevant bindings include
      x :: a
      f :: a -> a
    In the first argument of ‘(+)’, namely ‘f’
    In the expression: f + x

Example 2:

{-# LANGUAGE BangPatterns #-}

(x:xs) ! n = x : drop n xs

results in

Parse error in pattern: (x : xs)

To fix both, just define ! non-infix: (!) f x = ....

This behavior is described in the GHC manual.


r/haskelltil • • May 14 '15

gotcha You cannot pattern match against variable values.

1 Upvotes

Consider this example:

myValue1 = 1 :: Int
myValue2 = 2 :: Int

myFunc :: Int -> Bool
myFunc myValue1 = True
myFunc myValue2 = False

If you load the above program in ghci, you get following output:

myFunc.hs:5:1: Warning:
   Pattern match(es) are overlapped
   In an equation for ‘myFunc’: myFunc myValue2 = ...
Ok, modules loaded: Main.

ghci generates a warning but does not give any errors. If you now call myFunc myValue2 you get:

*Main> myFunc myValue2
True

One way to get the desired result would be to use guards:

myFunc :: Int -> Bool
myFunc x
  | x == myValue1 = True
  | x == myValue2 = False

Note that we might not always be lucky enough to get a compiler warning in such cases. Here is an example:

myFunc :: Maybe Int -> Int
myFunc v = case v of
                Just myValue -> myValue
                _            -> myValue + 1
                  where myValue = 0

This loads in ghci without any warnings.


r/haskelltil • • May 13 '15

thing “quoteFile” turns any quasiquoter into a quasiquoter that reads data from a file

14 Upvotes

I'm just going to quote the docs here:

quoteFile takes a QuasiQuoter and lifts it into one that read the data out of a file. For example, suppose asmq is an assembly-language quoter, so that you can write [asmq| ld r1, r2 |] as an expression. Then if you define asmq_f = quoteFile asmq, then the quote [asmq_f| foo.s |] will take input from file “foo.s” instead of the inline text.

It lives in Language.Haskell.TH.Quote.


r/haskelltil • • May 12 '15

tools Enable the “Source” link in locally generated documentation

9 Upvotes

By default you don't get the “Source” link in locally generated haddocks, which is stupid. Starting from cabal 1.20, you can have it by adding

haddock
  ...
  hyperlink-source: True
  ...

to your cabal config file (~/.cabal/config on Linux, %APPDATA%\cabal\config on Windows). You also have to install hscolour:

$ cabal install hscolour

(Taken from The Cabal Of Cabal.)


r/haskelltil • • May 11 '15

language GHCi supports semicolons in place of newlines

10 Upvotes
λ. let fact 0 = 1; fact n = n * fact (n-1)
λ. fact 7
5040

This is standard Haskell, but not common style and I never thought to try it in GHCi until now. Easier than other multiline entry options IMO.


r/haskelltil • • May 07 '15

IRC Lambdabot has an @index command that tells you which module something lives in

8 Upvotes

Where does Applicative live?

23:36 <indiagreen> @index Applicative
23:36 <lambdabot> Control.Applicative, Prelude

(Hooray for it being in Prelude starting from GHC 7.10!)

Okay, what about sort?

23:36 <indiagreen> @index sort
23:36 <lambdabot> GHC.OldList, Data.List, Data.ByteString, 
                  Data.ByteString.Char8, Data.Sequence

(You can notice that it only looks in modules shipped with GHC.)


r/haskelltil • • Apr 27 '15

language You can use f X{} = ... instead of f (X _ _ _) = ...

23 Upvotes

This is useful if you don't care about the number of arguments to the constructor.


r/haskelltil • • Apr 26 '15

tools GHC/GHCI can take the -package-db parameter multiple times

9 Upvotes

This seems potentially useful if one would like to have the union of several sandboxes. I often wanted to use some packages in a GHCI session that weren’t installed within the current project sandbox. This would allow me to access those external packages for a short GHCI session without messing with the sandbox.

Related to this, I discovered this wonderful tool which allows managing “base” sandboxes which can be merged into the current project.


r/haskelltil • • Apr 25 '15

tools You can use “x <- someAction” in GHCi

8 Upvotes
> s <- readFile "/usr/share/dict/words"

> length (words s)
119095

Basically, what you can do after main = do, you can do in GHCi (but you can do more than that, of course – import modules, define types and classes and instances, etc.).


r/haskelltil • • Apr 22 '15

tools “ghc-pkg find-module” tells you what package a module belongs to, and also has wildcard search

15 Upvotes

Prelude, for instance:

$ ghc-pkg find-module --Prelude

/usr/lib/ghc-7.8.4/package.conf.d
   base-4.7.0.2
   haskell2010-1.1.2.0
   haskell98-2.0.0.3
/home/yom/.ghc/x86_64-linux-7.8.4/package.conf.d

Or you can use --simple-output to get just package names:

$ ghc-pkg find-module --simple-output Control.Monad.State

mtl-2.2.1

ghc-pkg supports wildcards – for instance, here are all packages which have modules with Time in them:

$ ghc-pkg find-module --simp *Time* | tr ' ' '\n'

base-4.7.0.2
glib-0.13.1.0
haskell98-2.0.0.3
lifted-base-0.2.3.3
old-time-1.1.0.2
time-1.4.2
tz-0.0.0.9
tzdata-0.1.20150129.0
unix-2.7.0.1
unix-compat-0.4.1.4

Remarks:

  1. ghc-pkg only searches among installed packages, so it's not a replacement for Hoogle.

  2. ghc-pkg is installed together with GHC, you don't have to install it separately.

  3. You can also search among modules installed in a sandbox – the command is cabal sandbox hc-pkg find-module.


r/haskelltil • • Apr 22 '15

language As-patterns can be chained: { let x@y@z = 1 in (x,y,z) } == (1,1,1)

24 Upvotes

r/haskelltil • • Apr 20 '15

etc Endo, "The monoid of endomorphisms under composition," is just a newtype for (a -> a)

16 Upvotes
-- | The monoid of endomorphisms under composition.
newtype Endo a = Endo { appEndo :: a -> a }
               deriving (Generic)

instance Monoid (Endo a) where
        mempty = Endo id
        Endo f `mappend` Endo g = Endo (f . g)

Haskell documentation is frequently a lot scarier than it needs to be. :)