22 August, 2019
Haskell Cheat Sheet
Basics
Infix style
10 `div` 2Data Types
data Bool = False | True
-- [1] [2]- Type constructor
- Data constructor
data Pair a = Pair a a
-- record type
data Person = Person { name :: String }
p1 = Person "Name"
p2 = Person { name = "Name" }newtype Age = Age Int- newtype just a efficient wrapper around single value
if then else
if X then 22 else 23pattern matching
case x == y of
True -> "t"
False -> "f"Guards
myAbs x
| x < 0 = (-x)
| otherwise = xInside case statement
case maybeInt of
Just x | x > 0 -> Just x
_ -> NothingLists
Split lists
import Data.List.Split
splitOn "," "a,b,c,d"Typeclasses
class Eq a where
(==) :: a -> a -> Bool
data Days = Mon | Tue
instance Eq Days where
(==) Mon Mon = True
(==) Tue Tue = True
(==) _ _ = False
-- Typeclass requiring some other Typeclass for m
class Applicative m => Monad (m :: * -> *) wheredo syntax
main = do
name <- readName
return name
[1]return :: Monad m => a -> m a
Symbols
(>>=) :: Monad m => m a -> (a -> m b) -> m b
maybeA >>= atToMaybeB
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<$) :: Functor f => a -> f b -> f a
toMaybeB <$ maybeA -- but returns maybeA
-- dropping result of right or left
(<*) :: Applicative f => f a -> f b -> f a
(*>) :: Applicative f => f a -> f b -> f bIO
Files
withFile "path" ReadMode (\handler -> hGetContents handler)
-- or
readFile "path"The difference is, that hGetContents lazily reads the file, meaning only when you use the result, it actually reads from the file what you need. Downside is, if you read outside of the scope of the withFile function, you get an exception, as the file handle was closed already.
Exceptions
try :: Exception e => IO a -> IO (Either e a)
-- defined in terms of catch
catch :: Exception e => IO a -> (e -> IO a) -> IO aYou need to define what exceptions to consider, others are not handled, e.g. IOException for all IO errors.
System
exitWith :: ExitCode -> IO a
exitFailure :: IO aLibs
Printing text
import qualified Data.ByteString.Char8 as BS
import qualified Data.Text.IO as TIO
TIO.putStrLn "Text"
BS.putStrLn json
Language Extensions
LambdaCase
Allows:
\case
Just v -> doX
Nothing -> doYREPL
Query Type
Prelude> :type "string"
Run REPL in project
stack repl inside project or cabal repl
Projects
Header
module What (Import1, Import2) where
-- codeImporting
import qualified Data.Bool
[1]Data.Bool.boolcan now not be called directly anymore, only fully qualified
import qualified Data.Bool as B
[1]- Like this call with
B.boolfor renaming
Debugging
import Debug.Trace.trace
trace "This is logged" thisIsReturned