Haskell

Language

deriving - types that can be derived

type for types that…
Bounded with finite upper and lower bounds
Eq can be compared for equality
Ord have a total ordering (extends Eq)
Ix support indexing into a range
Read can be parsed from strings
Show can be converted into strings
Enum can be converted to and from integers

pragmas

LANGUAGE to enable language extensions
MINIMAL to define the minimal functions that should be defined on a class, comma separated, supports (¦)

module (and exports)

  • each file contains a module
  • the basic unit of organization in Haskell
  • the module Main that defines main, can have any filename
  • src/Examples/ExampleOne.hs -> Examples.ExampleOne
CODE DESCRIPTION
module ModuleName where by default, exports ALL
module ModuleName ( exports foo
foo  
TypeFoo(TypeFooConst, fieldSelector)  
) where  
module ModuleName ( exports all constructors and fieldselectors
TypeFoo(..) of TypeFoo
) where  
module ModFoo re-exporting ModBar,
( module Baz using the local alias "Baz"
) could have used the original name instead
where  
import Other.ModBar as Baz  

imports

  example description
import ALL import Data.List brings everything in
import () import Data.List (intercalate) brings ONLY …
as import Data.ByteString as BS brings everything in AND under BS.
as qualified import qualified Data.ByteString as BS brings it only under BS.
hiding import Prelude hiding (foldl, foldr) brings ALL except …
type import import Data.Text (Text) to use Text type identifier directly
+ qualified import qualified Data.Text as T  
  • you can assign the same import (as) alias to different modules
  • NOTE: here "brings" means, get it into this module's direct access

operators

simples

$ function application map ($ 10) [(+ 1)]    
$! strict function application      
. function composition printLn . show    
++ append lists [1,2] ++ [3,4] [1,2,3,4] [a] -> [a] -> [a]
<> append strings (mappend) "foo" <> "bar" "foobar" m -> m -> m
!! list indexing [1,2] !! 0 1 [a] -> Int -> a
: list consing, preppending 1 : [2, 3] [1,2,3] a -> [a] -> [a]
== equal 1 == 2 False a -> a -> Bool
/= not equal 1 == 2 True a -> a -> Bool

typeclasses

op description   fn signature
<> mappend Semigroup a a -> a -> a
<$> fmap Functor f (a -> b) -> f a -> f b
>>= bind Monad m m a -> (a -> m b) -> m b
=<< flipped bind Monad m (a -> m b) -> m a -> m b
>> then Monad m m a -> m b -> m b
>=> monadic composition, fish op Monad m (a -> m b) -> (b -> m c) -> (a -> m c)
<=< flipped kleiski fish Monad m (b -> m c) -> (a -> m b) -> (a -> m c)
<$   Functor f a -> f b -> f a
<¦> Control.Alternative Alternative f f a -> f a -> f a
<*> apply Applicative f f (a -> b) -> f a -> f b
*> left "facing bird"/shark Applicative f f a -> f b -> f b
<* right "facing bird"/shark Applicative f f a -> f b -> f a

types

type String = [Char] -- a type alias

-- can only have ONE contructor with ONE argument
-- can be made an instance
newtype StepName = StepName Text
  deriving (Eq, Show)

data Pipeline = Pipeline { steps :: [Step] }
  deriving (Eq, Show)

types primitives

type eg description  
Bool True boolean, short-circuits due laziness  
Integer 2 signed integer, unbounded  
Int 2 signed integer, 32/64 bit  
Word 2 unsigned integer, 32/64 bit  
Float 1.2 IEEE single-precision floating-point  
Double 1.2 IEEE double-precision floating-point  
Char 'A' an unicode code point Data.Char
  '\9835'    
String "foo" list characters  
Ratio 1 % 3   Data.Ratio
  • String
    • string gaps within a string literal, two backslashes with a whitespace between them form a gap in the string. Removed during compilation.

      "Your password cannot be \
      \longer than 20 characters."
      

types complex

instancing possible definition name description
[1,2] [Int] (linked) list  
"foo" type A = String type alias  
0 :¦ [1,2] data NonEmpty a = a :¦ [a] non empty list Data.List.NonEmpty
A "foo" newtype A = A String type "safe" alias can have only 1 type
      no alternatives
C "foo" data A a data can have >1 type per construct
  = C String Int    
  ¦ D a   can have alternatives with ¦
C {foo = 1} data A = C { foo :: Int } data records automatically creates getters
      avoid clashes by prefixing field names
      syntax to update a field
      x1 {foo = 2}
Tuple 2 "foo" data Tuple a b = Tuple a b data tuple we are able to plug differen types
(2, "foo")     polymorphic definition
Left "Hello" data Either a b   useful for modeling errors
Right 17 = Left a   Right = we got what we wanted
  ¦ Right b   Left = we got an error
  • tuples (aka anonymous products)

Standard Library

Prelude.hs functions

https://www.cse.chalmers.se/edu/year/2018/course/TDA452_Functional_Programming/tourofprelude.html#init

fn returns description
all Bool  
any Bool  
concatMap [a] map + concat
dropWhile [a] drops from head while fn is True
filter [a]  
uncurry (a,b) -> c takes a fn that takes 2 args, and returns a fn that takes a pair
curry a -> b -> c takes a fn that takes a pair, and returns a fn that takes 2 args
flip b -> a -> c returns the same function with argumnts flipped
fold t m -> m folds a Foldable+Monoid
foldl a folds left
foldl1 a folds left over NON EMPTY lists
foldr a folds right
foldr1 a folds right over NON EMPTY lists
iterate [a] returns the infinity list of applying [fn x, fn (fn x),…]
map [b]  
span ([a],[a]) split list into 2 tuple, pivot when fn returns False
break ([a],[a]) split list into 2 tuple, pivot when fn returns True
takeWhile [a] returns elems from head, while fn returns True
until [a] returns elems from head, until fn returns False
zipWith [c] applies a binary function and two list
repeat [a] repeats an infinite in an list, the value provided
replicate [a] repeats N-times in a list, the value provided
concat [a] flattens a list of lists
head a first element on a NON EMPTY list
tail [a] aka cdr
last a last element on a NON EMPTY list
init [a] aka butlast
sort [a] sorts in ascending order
reverse [a] reverse a list
maximum a returns max element on a NON EMPTY list
minimum a returns min element on a NON EMPTY list
length int  
null Bool true if empty list
and Bool applied to a list of booleans
or Bool applied to a list of booleans
product int aka reduce #'*
sum int aka reduce #'+
++ [a] append 2 lists
zip [(a,b)] applied to 2 lists, returns a list of pairs
elem Bool aka exists? on list
notElem Bool aka NOT exists? on list
!! a indexing a list
splitAt ([a],[a]) splits at index
take a aka subseq 0 N
drop [a] aka nthcdr
lines [String] split String by new line
unlines String list of strings into string
words [String]  
unwords String  
digitToInt Int char to int
chr Char takes an integer
ord Int ascii code for char
toLower Char  
toUpper Char  
compare Ordering  
error a takes a string and errors
max a max between 2 elements
succ a next value on an Enum, error if last
pred a previous value on an Enum, error if first
fst a first element on a two element tuple
snd b second element on a two element tuple
maybe b applied fn to Maybe value, or the default value provided
print IO () putStrLn . show
putChar IO ()  
putStr IO () prints string
show String  
isSpace Bool  
isAlpha Bool if char is alphabetic
isDigit Bool if char is a number
isLower Bool  
isUpper Bool  
ceiling   smallest integer, not less than argument
floor   greatest integer, not greater than argument
round   nearest integer
truncate   drops the fractional part
mod    
quot    
rem    
** Floating raises, arguments must be Floating
^ Num raises, Num by Integral
^^ Fractional raises, Fractional by Integral

base

module / description fn  
Control.Applicative    
Control.Arrow    
Control.Category    
Control.Concurrent    
  forkIO IO () -> IO ThreadedId
Control.Concurrent.MVar   a synchronization variable (mutex?)
  newMVar IO (MVar a)
  newEmptyMVar IO (MVar a)
  readMVar MVar a -> IO a
  takeMVar MVar a -> IO a
  putMvar MVar a -> a -> IO ()
  tryReadMVar MVar a -> IO (Maybe a)
  tryTakeMVar MVar a -> IO (Maybe a)
  modifyMVar MVar a -> (a -> IO (a,b)) -> IO b
Control.Concurrent.Chan newChan IO (Chan a)
  writeChan Chan a -> a -> IO ()
  readChan Chan a -> IO a
Control.Exception    
  catch Exception e => IO a -> (e -> IO a) -> IO a
  handle Exception e => (e -> IO a) -> IO a -> IO a
  ioError IOError -> IO a
  throw Exception e => e -> a
  throwIO Exception e => e -> IO a
acq,rel,use of resource bracket IO r -> (r -> IO a) -> (r -> IO b) -> IO b
  bracket_ IO a -> IO b -> IO c -> IO c
Control.Exception.Safe tryAny IO a -> IO (Either SomeException a)
Control.Monad    
"flattens" a monad join Monad m => m (m a) -> m a
monadic composition >=> Monad m => (a -> m b) -> (b -> m c) -> a -> m c
  <=< Monad m => (b -> m c) -> (a -> m b) -> a -> m c
  <$ Functor f => a -> f b -> f a
repeats input IO () forever Applicative f => f a -> f b
could take IO () when Applicative f => Bool -> f () -> f ()
  guard Alternative f => Bool -> f ()
could take [IO ()] sequence (Monad m, Traversable t) => t (m a) -> m (t a)
  sequence_ (Monad m, Foldable t) => t (m a) -> m ()
sequence $ map f mapM (Monad m, Traversable t) => (a -> m b) -> t a -> m (t b)
same but no return mapM_ (Monad m, Foldable t ) => (a -> m b) -> t a -> m ()
flipped mapM forM (Monad m, Traversable t) => t a -> (a -> m b) -> m (t b)
  forM_ (Monad m, Foldable t ) => t a -> (a -> m b) -> m ()
aka fmap liftM Monad m => (a -> b) -> m a -> m b
aka <$> (applicative) ap Monad m => m (a -> b) -> m a -> m b
  filterM Monad m => (a -> m Bool) -> [a] -> m [a]
discards the result void Functor f => f a -> f ()
Control.Monad.IO.Class liftIO IO a -> m a
Control.Monad.Fail fail MonadFail m => String -> m a
Data.Bifoldable    
Data.Bifoldable1    
Data.Bifunctor    
Data.Bitraversable    
Data.Bits    
Data.Bool    
Data.Char isPrint  
  ord Char -> Int
  chr Int -> Char
Data.Coerce    
Data.Complex    
Data.Data    
Data.Dynamic    
Data.Either    
Data.Eq    
Data.Fixed    
Data.Foldable for_ (Foldable t, Applicative f) => t a -> (a -> f b) -> f ()
Data.Foldable1    
Data.Function    
Data.Functor    
Data.IORef    
Data.Int   Int8/64
Data.Ix    
Data.Kind    
Data.List   permutations splitAt
Data.Maybe    
apply f, with default b maybe b -> (a -> b) -> Maybe a -> b
  mapMaybe (a -> Maybe b) -> [a] -> [b]
  listToMaybe [a] -> Maybe a
  maybeToList Maybe a -> [a]
Data.Fixed mod' Real a => a -> a -> a
Data.Monoid    
Data.Ord    
Data.Proxy    
Data.Ratio    
Data.STRef    
Data.Semigroup    
Data.String    
Data.Traversable    
Data.Tuple    
Data.Typeable    
Data.Unique    
Data.Version    
Data.Void    
Data.Word    
Debug.Trace    
print dynamic msg 1°arg trace String -> a -> a
print static msg traceId String -> String
  traceShow Show a => a -> b -> b
  traceShowId Show a => a -> a
Foreign   interfacing with another programming language
Foreign.C.Types   CInt, CUint
Foreign.Ptr nullPtr Ptr a
  castPtr Ptr a -> Ptr b
  plusPtr Ptr a -> Int -> Ptr b
Foreign.Marshall.Alloc allocaBytes Int -> (Ptr a -> IO b) -> IO b
  mallocBytes Int -> IO (Ptr a)
Foreign.Marshal.Utils copyBytes Ptr a -> Ptr a -> Int -> IO ()
Foreign.Storable peek Ptr a -> IO a
  peekByteOff Ptr b -> Int -> IO a
GHC.Float float2Int Float -> Int
  int2Float Int -> Float
Numeric.Natural Natural a type of non negative number
  minusNaturalMaybe Natural -> Natural -> Maybe Natural
System.CPUTime    
System.Console    
System.Environment getArgs IO [String]
  withArgs [String] -> IO a -> IO a
System.Exit    
  data ExitCode = ExitSuccess ¦ ExitFailure Int
stderr msg+exitFailure die String -> IO a
  exitWith ExitCode -> IO a
  exitSuccess IO a
  exitFailure IO a
System.Info    
System.Mem    
System.Posix    
System.Timeout    
System.IO openFile FilePath -> IOMode -> IO Handle
  withFile FilePath -> IOMode -> (Handle -> IO r) -> IO r
  openBinaryFile FilePath -> IOMode -> IO Handle
  hSetBinaryMode Handle -> Bool -> IO ()
  hClose Handle -> IO ()
  hGetContents Handle -> IO String
  hputStrLn Handle -> IO ()
  putStrLn String -> IO ()
  stdout Handle
System.IO.Error userError String -> IOError
Text.ParserCombinators    
  • Control.Concurrrent.MVar

    MVar problems due…
    race conditions forgotten locks
    deadlocks inconsistent lock ordering
    corruption uncaught exceptions
    lost wakeups ommited notifications
  • Control.Concurrent.Chan
    • reads block until there is a value to read
    • writes never block

non base

package module functions
array Data.Array  
containers Data.Graph  
  Data.IntMap  
  Data.IntSet  
  Data.Map  
  Data.Sequence  
  Data.Set  
  Data.Tree  
binary Data.Binary  
bytestring Data.ByteString efficiently dealing with files
    hPut :: Handle -> ByteString -> IO ()
    hGetSome :: Handle -> Int -> IO ByteString
    null :: ByteString -> Bool
    pack :: [Word8] -> ByteString
    unpack :: ByteString -> [Word8]
  Data.ByteString.Lazy fromStrict toStrict
  Data.ByteString.Char8 instead of Word8
deepseq Control.DeepSeq  
directory System.Directory  
    getHomeDirectory :: IO FilePath
    getCurrentDirectory :: IO FilePath
    setCurrentDirectory :: FilePath -> IO ()
    getDirectoryContents :: FilePath -> IO [FilePath]
    getAppUserDataDirectory :: FilePath -> IO FilePath
exceptions Control.Monad.Catch  
filepath System.FilePath  
  System.OsPath  
  System.OsString  
haskeline System.Console  
hoopl Compiler.Hoopl  
hpc Trace.Hpc  
integer-gmp GHC.Integer.GMP  
libiserv    
mtl Control.Monad.Accum  
  Control.Monad.Cont  
  Control.Monad.Except  
  Control.Monad.Identity  
  Control.Monad.RWS  
  Control.Monad.Reader  
  Control.Monad.Select  
  Control.Monad.State  
  Control.Monad.Trans  
  Control.Monad.Writer  
network Network.Socket socket :: Family -> SocketType -> ProtocolNumber -> IO Socket
    getAddrInfo :: Maybe AddrInfo -> Maybe HostName -> Maybe ServiceName -> IO [AddrInfo]
    tupleToHostAddress :: (Word8,Word8,Word8,Word8) -> HostAddress
    connect :: Socket -> SockAddr -> IO ()
    gracefulClose :: Socket -> Int -> IO ()
    setSocketOption :: Socket -> SocketOption -> Int -> IO ()
  Network.Socket.ByteString  
    sendAll :: Socket -> ByteString -> IO ()
    recv :: Socket -> Int -> IO ByteString
parsec Text.Parsec  
  Text.ParserCombinators.Parsec  
pretty Text.PrettyPrint  
process System.Cmd DEPRECATED
  System.Process  
    shell :: String -> CreateProcess
    proc :: FilePath -> [String] -> CreateProcess
    createProcess :: CreateProcess -> IO (Maybe Handle, MH, MH, ProcessHandle)
  sync callProcess :: FilePath -> [String] -> IO ()
  sync callCommand :: String -> IO ()
  async spawnProcess :: FilePath -> [String] -> IO ProcessHandle
  async spawnCommand :: String -> IO ProcessHandle
  (deprecated) rawSystem :: String -> [String] -> IO GHC.IO.Exception.ExitCode
  (deprecated) system :: String -> IO ExitCode
terminfo System.Console.Terminfo  
template-haskell Language.Haskell.TH  
text Data.Text efficient/strict String unicode++
    pack :: String -> Text
    unpack :: Text -> String
    hGetChunk :: Handle -> IO Text
    hGetLine
    null :: Text -> Bool
    uncons :: Text -> Maybe (Char, Text)
    unsnoc :: Text -> Maybe (Text, Char)
    snoc :: Text -> Char -> Text
    cons :: Char -> Text -> Text
  Data.Text.IO hPutStrLn :: Handle -> Text -> IO ()
  Data.Text.Encoding d/encodeUtf8 - to/from ByteString
time Data.Time formatTime :: FormatTime t => TimeLocale -> String -> t -> String
    parseTimeM :: (MF m, TL t) => Bool -> TimeLocale -> String -> String -> m t
    utcToLocalTime :: TimeZone -> UTCTime -> LocalTime
    utcToZonedTime :: TimeZone -> UTCTime -> ZonedTime
    utctDay :: UTCTime -> Day
    toGregorian :: Day -> (Integer, Int, Int)
    defaultTimeLocale :: TimeLocale
    getCurrentTimeZone :: TimeZone
    getCurrentTime :: UTCTime
    UTCTime = point in time, utc
    Day = point in time, local in days
    LocalTime = point in time, local in picoseconds
    NominalDiffTime = time interval, utc
    CalendarDiffDays = time interval, local in days
    CalendarDiffTime = time interval, local in picoseconds
transformers Control.Monad.Trans  
stm   transactional memory (optimistic acquisition, pessimist commit)
  Control.Concurrent.STM  
  Control.Concurrent.STM.TVar aka Transactional Variable
    newTVar :: a -> STM (TVar a)
    readTVar :: TVar a -> STM a
    writeTVar :: TVar a -> a -> STM ()
    modifyTVar :: TVar a -> (a -> a) -> STM ()
    modifyTVar' :: TVar a -> (a -> a) -> STM ()
  Control.Monad.STM atomically :: STM a -> IO a
    orElse :: STM a -> STM a -> STM a
    check :: Bool -> STM ()
    retry :: STM a
    throwSTM :: Exception e => e -> STM a
    catchSTM :: Exception e => STM a -> (e -> STM a) -> STM a
unix System.Posix  
xhtml Text.XHtml  
  • stm
    • STM type is abstract
    • STM actions cannot be interleaved with IO actions

typeclasses

recap.png

lift(s)

  • liftM (aka monadic fmap, bind??) Control.Monad

    liftM :: Monad m => (a -> b) -> m a -> m b
    
  • liftIO - Control.Monad.IO.Class

    class (Monad m) => MonadIO m where -- aka any Monad that an IO can be lifted INTO
      liftIO :: IO a -> m a
    
  • liftA2 - Control.Applicative

    • apply a function between several functor values
    • aka takes a normal binary function and promotes it to a function that operates on two applicatives
    liftA2 :: (Applicative f) => (a -> b -> c) -> (f a -> f b -> f c)
    liftA2 f a b = f <$> a <*> b
    

do

  • When to use (>>=) and when use do?
    1. if it seems like you're writing way Too Many Lambdas use do
    2. Too many variables that get introduced on one line, only to get used on the next, use (>>=)
    3. Or use both

      do
        x1 <- a1 >>= f1 >>= f2
        x2 <- a2 >>= f3 >>= f4
        f5 x1 x2
      

Shipped

  MINIMAL description extras
Foldable foldr foldMap data structure that can be folded foldr foldl null length sum product maximum minim elem
Show show conversion of values to readable String's  
Eq (==) (=/) equality and inequality  
Ord compare (<=)   max min < > <= >=
Enum toEnum, fromEnum can be enumerated by the Int value [Foo..Bar]
Bounded minBound, maxBound with minimum and maximum bounds  
Functor fmap (<$>) can be mapped over  
Semigroup (<>) associative binary op sconcat stimes
Monoid mempty associative binary op with identity mconcat mappend (<>)
Applicative pure (<*>) a functor, sequence and combine ops  
Alternative empty (<¦>) returns the first one that doesn "fail"  
Monad bind (>>=)   do (=<<)
IsString fromString OverloadedStrings implicitly runs it -
  • IsString defined in Data.String
  • Show
    • exists for the sake of GHCi and for testing, not for real use in applications
    • we recommend never allowing the behavior of your program to depend on the show function
definitions
 class Eq a where
   (==) :: a -> a -> Bool

 class Monoid a where
   mempty  :: a           -- neutral element
   mappend :: a -> a -> a -- associative binary operation
   mconcat :: [a] -> a

 class Semigroup a where
   (<>) :: a -> a -> a
 class Semigroup a => Monoid a where ... -- since GHC 8.4

 class Functor f where
   fmap :: (a -> b) -> f a -> f b

 class (Functor f) => Applicative f where -- class constraint
   pure  :: a -> f a
   (<*>) :: f (a -> b) -> f a -> f b -- (ME: apply a wrapped function to a wrapped value)

 class Foldable t where
   foldMap :: Monoid m => (a -> m) -> t a -> m
   foldr   :: (a -> b -> b) -> b -> t a -> b
   fold    :: Monoid m => t m -> m
   foldr'  :: (a -> b -> b) -> b -> t a -> b
   foldl   :: (a -> b -> a) -> a -> t b -> a
   foldl'  :: (a -> b -> a) -> a -> t b -> a
   foldr1  :: (a -> a -> a) -> t a -> a
   foldl1  :: (a -> a -> a) -> t a -> a

 class Monad m where -- 🪠
   (>>=) :: m a
-> (a -> m b) -> m b -- (ME: apply a function that returns a wrapped value to a wrapped value)

 class IsString a where
   fromString :: String -> a

 class Applicative f => Alternative f where -- Control.Alternative
   empty :: f a               -- a computation with zero results
   (<|>) :: f a -> f a -> f a -- combines two computations, returns the first "successful" one (it "recovers" from failure)

 class Monad m => MonadPlus m where
   mzero :: a                 -- equivalent to empty
   mplus :: m a -> m a -> m a -- equivalent to mplus

Declaring

class Eq a where -- name=Eq - type_variable=a -- posible class constraint goes here, after class, before =>
  (==), (/=) :: a -> a -> Bool -- they share the same signature
  {-# INLINE (/=) #-} -- GHC pragma to define inline methods?
  {-# INLINE (==) #-}
  x /= y = not (x == y) -- default implementation
  x == y = not (x /= y)
  {-# MINIMAL (==) | (/=) #-} -- minimal complete definition, either

Codebases

Snippets

yes

https://theory.stanford.edu/~blynn/c2go/

import Control.Monad
import System.Environment

main :: IO ()
main =
  getArgs >>= forever . putStrLn . f
  where
    f [] = "y"
    f xs = unwords xs

Definition of forever on Control.Monad (possibly)

forever :: IO () -> IO ()
forever a = a >> forever a -- OR
forever a = do a; forever a

reading a file + system + aeson

https://haskell-works.github.io/posts/2018-07-25-problem-of-parsing-large-datasets.html

import Control.Monad
import Data.Aeson
import GHC.Stats
import System.Posix.Process
import System.Process

import qualified Data.ByteString.Lazy as BS
import qualified System.Environment   as IO

main :: IO ()
main = do
  pid <- getProcessID
  (filename:_) <- IO.getArgs
  bs <- BS.readFile filename
  let !maybeJson = decode bs :: Maybe Value

  system $ "ps aux | grep " <> show pid <> " | grep -v grep"

  forM_ maybeJson $ \_ ->
    putStrLn "Done"

Created: 2019-01-01

Updated: 2024-11-16

Back