An advanced, purely functional programming language

Declarative, statically typed code.

primes = filterPrime [2..]
  where filterPrime (p:xs) =
          p : filterPrime [x | x <- xs, x `mod` p /= 0]

Try it!


Statically typed

被窝里的公息第十三章Every expression in Haskell has a type which is determined at compile time. All the types composed together by function application have to match up. If they don't, the program will be rejected by the compiler. Types become not only a form of guarantee, but a language for expressing the construction of programs.

Click to expand

All Haskell values have a type:

char = 'a'    :: Char
int = 123     :: Int
fun = isDigit :: Char -> Bool

You have to pass the right type of values to functions, or the compiler will reject the program:

Type error
isDigit 1

You can decode bytes into text:

bytes = Crypto.Hash.SHA1.hash "hello" :: ByteString
text = decodeUtf8 bytes               :: Text

But you cannot decode Text, which is already a vector of Unicode points:

Type error
doubleDecode = decodeUtf8 (decodeUtf8 bytes)

Purely functional

被窝里的公息第十三章Every function in Haskell is a function in the mathematical sense (i.e., "pure"). Even side-effecting IO operations are but a description of what to do, produced by pure code. There are no statements or instructions, only expressions which cannot mutate variables (local or global) nor access state like time or random numbers.

Click to expand

The following function takes an integer and returns an integer. By the type it cannot do any side-effects whatsoever, it cannot mutate any of its arguments.

square :: Int -> Int
square x = x * x

被窝里的公息第十三章The following string concatenation is okay:

"Hello: " ++ "World!" 

The following string concatenation is a type error:

Type error
"Name: " ++ getLine

Because getLine has type IO String and not String, like "Name: " is. So by the type system you cannot mix and match purity with impurity.

Type inference

You don't have to explicitly write out every type in a Haskell program. Types will be inferred by unifying every type bidirectionally. However, you can write out types if you choose, or ask the compiler to write them for you for handy documentation.

Click to expand

This example has a type signature for every binding:

main :: IO ()
main = do line :: String <- getLine
          print (parseDigit line)
  where parseDigit :: String -> Maybe Int
        parseDigit ((c :: Char) : _) =
          if isDigit c
             then Just (ord c - ord '0')
             else Nothing

被窝里的公息第十三章But you can just write:

main = do line <- getLine
          print (parseDigit line)
  where parseDigit (c : _) =
          if isDigit c
             then Just (ord c - ord '0')
             else Nothing

被窝里的公息第十三章You can also use inference to avoid wasting time explaining what you want:

do ss <- decode "[\"Hello!\",\"World!\"]"
   is <- decode "[1,2,3]"
   return (zipWith (\s i -> s ++ " " ++ show (i + 5)) ss is)
 => Just ["Hello! 6","World! 7"]

被窝里的公息第十三章Types give a parser specification for free, the following input is not accepted:

do ss <- decode "[1,2,3]"
   is <- decode "[null,null,null]"
   return (zipWith (\s i -> s ++ " " ++ show (i + 5)) ss is)
 => Nothing


被窝里的公息第十三章Haskell lends itself well to concurrent programming due to its explicit handling of effects. Its flagship compiler, GHC, comes with a high-performance parallel garbage collector and light-weight concurrency library containing a number of useful concurrency primitives and abstractions.

Click to expand

Easily launch threads and communicate with the standard library:

main = do
  done <- newEmptyMVar
  forkIO (do putStrLn "I'm one thread!"
             putMVar done "Done!")
  second <- forkIO (do threadDelay 100000
                       putStrLn "I'm another thread!")
  killThread second
  msg <- takeMVar done
  putStrLn msg

Use an asynchronous API for threads:

do a1 <- async (getURL url1)
  a2 <- async (getURL url2)
  page1 <- wait a1
  page2 <- wait a2

被窝里的公息第十三章Atomic threading with software transactional memory:

transfer :: Account -> Account -> Int -> IO ()
transfer from to amount =
  atomically (do deposit to amount
                 withdraw from amount)

Atomic transactions must be repeatable, so arbitrary IO is disabled in the type system:

Type error
main = atomically (putStrLn "Hello!")


被窝里的公息第十三章Functions don't evaluate their arguments. This means that programs can compose together very well, with the ability to write control constructs (such as if/else) just by writing normal functions. The purity of Haskell code makes it easy to fuse chains of functions together, allowing for performance benefits.

Click to expand

Define control structures easily:

when p m = if p then m else return ()
main = do args <- getArgs
          when (null args)
               (putStrLn "No args specified!") 

If you notice a repeated expression pattern, like

if c then t else False

you can give this a name, like

and c t = if c then t else False

and then use it with the same effect as the orginal expression.

Get code re-use by composing lazy functions. It's quite natural to express the any function by reusing the map and or被窝里的公息第十三章 functions:

any :: (a -> Bool) -> [a] -> Bool
any p = or . map p

Reuse the recursion patterns in map, filter, foldr, etc.


Open source contribution to Haskell is very active with a wide range of packages available on the public package servers.

Click to expand

There are 6,954 packages freely available. Here is a sample of the most common ones:

Binary data Prelude, IO, threads
Networking Unicode text
Parser library File/directory
RSpec-like tests Fast parser
Logging Database ORM
Meta-programming Tar archives
Web framework Date, time, etc.
Web framework Web framework
Maps, graphs, sets Watch filesystem
Interpret Haskell UNIX bindings
SDL binding OpenGL graphics system
Benchmarking Text rendering
Cairo graphics Statistical analysis
Gtk+ library GLib library
Testing framework Resource pooling
Streaming I/O High-quality randoms
Property testing Atomic threading
Markup generation Binary parsing/printing
XML parser/printer HTTP client engine
zlib/gzip/raw YAML parser/printer
Markup conversion Serialization
TLS/SSL Zip compression
Web server Text encodings
Vectors Async concurrency
Streaming IO Arbitrary-prec. nums
Launch processes JSON parser/printer
Difflists Generic prog.


被窝里的公息第十三章 provides powerful, customizable 24/7 metrics and monitoring integration for all of, and complains loudly for us when things go wrong.

's Next Generation CDN provides low latency access for all of's downloads and highest traffic services, including the primary Hackage server, Haskell Platform downloads, and more.

provides compute, storage, and networking resources, powering almost all of in several regions around the world.

被窝里的公息第十三章 powers , and lets us easily tell you when we broke something.

被窝里的公息第十三章 provides infrastructure, funds, administrative resources and has historically hosted critical infrastructure, as well as helping the Haskell community at large with their work.

has teamed up to provide with redundant, scalable object-storage through their Dream Objects service.

provides monitoring and escalation for core infrastructure.

Psst! Looking for the wiki?

被窝里的公息第十三章This is the new Haskell home page! The wiki has moved to