0% found this document useful (0 votes)
45 views76 pages

Prop A Cheat Sheet

Uploaded by

Mihai Tanase
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views76 pages

Prop A Cheat Sheet

Uploaded by

Mihai Tanase
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 76

λ

Funktionale Programmierung
Funktionale Programmierung
Begriffe
Haskell Prelude
Basic data types
Basic type classes
Numeric types
Numeric type classes
Numeric functions
Monads and functors
Folds and traversals
Miscellaneous functions
List operations
Special folds
Building lists
Sublists
Searching lists
Zipping and unzipping
Functions on strings
base
module Control.Applicative where
module Control.Monad where
module Data.Bifunctor where
module Data.Char where
module Data.Function where
module Data.List where
module Data.Ord where
module Data.Tuple where
module Numeric where
MissingH
module Data.List.Utils where
Begriffe Haskell Prelude
Eine Funktion heißt linear rekursiv, wenn in jedem Definitionszweig nur ein rekursiver Aufruf https://hackage.haskell.org/package/base-4.18.0.0/docs/Prelude.html
vorkommt. (https://hackage.haskell.org/package/base-4.18.0.0/docs/Prelude.html)

Eine linear rekursive Funktion heißt endrekursiv (tail recursive), wenn in jedem Zweig der Basic data types
rekursive Aufruf nicht in andere Aufrufe eingebettet ist.

-- nichtlinear rekursiv, O(2^n) rekursive Aufrufe  data Bool = False | True 


fib n
| (n == 0) = 0 Instances:  Bounded ,  Enum ,  Read ,  Show ,  Eq ,  Ord 
| (n == 1) = 1
| otherwise = fib (n - 1) + fib (n - 2) Signature Docs

-- endrekursiv mit Akkumulator, O(n) rekursive Aufrufe  (&&) :: Bool -> Bool -> Bool  Boolean “and”, lazy in the second
fib n = fibAcc n 0 1 ( infixr 3 ) argument
where
fibAcc n n1 n2  (||) :: Bool -> Bool -> Bool 
Boolean “or”, lazy in the second argument
| (n == 0) = n1 ( infixr 2 )
| (n == 1) = n2  not :: Bool -> Bool  Boolean “not”
| otherwise = fibAcc (n - 1) n2 (n1 + n2)
 otherwise  is defined as the value  True .
 otherwise :: Bool 
It helps to make guards more readable.
Funktionen, die andere Funktionen als Parameter erhalten oder Funktionen als
Rückgabewerte liefern, heißen Funktionen höherer Ordnung.

Currying ist die Ersetzung einer mehrstelligen Funktion durch Schachtelung einstelliger  data Maybe a = Nothing | Just a 
Funktionen. Funktionen in Haskell sind gecurryt. Funktionsanwendung ist linksassoziativ.
The  Maybe  type encapsulates an optional value. A value of type  Maybe a  either contains a
Extensionalitätsprinzip: f = g ⟺ ∀x ∈ A : f (x) = g(x) für alle f , g : A → B . value of type  a  (represented as  Just a ), or it is empty (represented as  Nothing ). Using
 Maybe  is a good way to deal with errors or exceptional cases without resorting to drastic
Bindungskonstrukte legen Bedeutung und Geltungsbereich von Variablen fest, z. B.
measures such as  error .
Funktionsdefinitionen und λ-Abstraktionen. Innere Bindungen verdecken äußere.
The  Maybe  type is also a monad. It is a simple kind of error monad, where all errors are
Referenzielle Transparenz: Im gleichen Gültigkeitsbereich bedeuten gleiche Ausdrücke stets
represented by  Nothing . A richer error monad can be built using the  Either  type.
das Gleiche. Zwei verschiedene Ausdrücke, die zum gleichen Wert auswerten, können stets
durch den anderen ersetzt werden, ohne die Bedeutung des Programms zu verändern. Instances:  Functor ,  Monad ,  Read ,  Show ,  Eq ,  Ord 
Fehlerhafte Auswertungen (⊥):
Signature Docs
Nichttermination, z. B.  fib (-1)  (s. o.)
The  maybe  function takes a default value,
Laufzeitfehler, z. B.  div 1 o  a function, and a  Maybe  value. If the
 maybe :: b -> (a -> b) -> Maybe a ->  Maybe  value is  Nothing , the function
b  returns the default value. Otherwise, it
applies the function to the value inside the
 Just  and returns the result.
Basic type classes
 data Either a b = Left a | Right b 
The  Either  type represents values with two possibilities: a value of type  Either a b  is  class Eq a where 
either  Left a  or  Right b .
The  Eq  class defines equality ( == ) and inequality ( /= ). All the basic datatypes exported
The  Either  type is sometimes used to represent a value which is either correct or an error;
by the Prelude are instances of  Eq , and  Eq  may be derived for any datatype whose
by convention, the  Left  constructor is used to hold an error value and the  Right 
constituents are also instances of  Eq .
constructor is used to hold a correct value (mnemonic: “right” also means “correct”).
The Haskell Report defines no laws for  Eq . However, instances are encouraged to follow
Instances:  Bifunctor ,  Foldable ,  Applicative ,  Functor ,  Monad ,  Read ,  Show ,  Eq ,
these properties:
 Ord 
Reflexivity:  x == x = True 
Signature Docs Symmetry:  x == y = y == x 
Case analysis for the  Either  type. If the Transitivity: if  x == y && y == z = True , then  x == z = True 
 either :: (a -> c) -> (b -> c) -> value is  Left a , apply the first function Extensionality: if  x == y = True  and  f  is a function whose return type is an instance
Either a b -> c  to  a ; if it is  Right b , apply the second of  Eq , then  f x == f y = True 
function to  b . Negation:  x /= y = not (x == y) 

Minimal complete definition:  (==) | (/=) 


 data Ordering = LT | EQ | GT 
Signature Docs
Instances:  Bounded ,  Enum ,  Read ,  Show ,  Eq ,  Ord   (==) :: a -> a -> Bool 
( infix 4 )

 data Char   (/=) :: a -> a -> Bool 


( infix 4 )
Instances:  Bounded ,  Enum ,  Read ,  Show ,  Eq ,  Ord 

Signature Docs  class Eq a => Ord a where 


A  String  is a list of characters. String
The  Ord  class is used for totally ordered datatypes.
 type String = [Char]  constants in Haskell are values of type
 String . Instances of  Ord  can be derived for any user-defined datatype whose constituent types are
in  Ord . The declared order of the constructors in the data declaration determines the
Tuples ordering in derived  Ord  instances. The  Ordering  datatype allows a single comparison to
determine the precise ordering of two objects.
Signature Docs  Ord , as defined by the Haskell report, implements a total order and has the following
 fst :: (a, b) -> a  Extract the first component of a pair. properties:

 snd :: (a, b) -> b  Extract the second component of a pair. Comparability:  x <= y || y <= x = True 
Transitivity: if  x <= y && y <= z = True , then  x <= z = True 
 curry :: ((a, b) -> c) -> a -> b ->  curry  converts an uncurried function to
c  a curried function. Reflexivity:  x <= x = True 
Antisymmetry: if  x <= y && y <= x = True , then  x == y = True 
 uncurry :: (a -> b -> c) -> (a, b) -  uncurry  converts a curried function to a
> c  function on pairs.
The following operator interactions are expected to hold:  x >= y = y <= x ,  x < y = x <= Signature Docs
y && x /= y ,  x > y = y < x ,  x < y = compare x y == LT ,  x > y = compare x y ==
GT ,  x == y = compare x y == EQ ,  min x y == if x <= y then x else y = True ,  max x the successor of a value. For numeric
 succ :: a -> a 
y == if x >= y then x else y = True  types, succ adds 1.

Minimal complete definition:  compare | (<=)  the predecessor of a value. For numeric
 pred :: a -> a 
types, pred subtracts 1.
Signature Docs  toEnum :: Int -> a  Convert from an  Int .
 compare :: a -> a -> Ordering  Convert to an  Int . It is implementation-
 (<) :: a -> a -> Bool  dependent what  fromEnum  returns when
 fromEnum :: a -> Int 
( infix 4 ) applied to a value that is too large to fit in
an  Int .
 (<=) :: a -> a -> Bool 
( infix 4 ) Used in Haskell’s translation of  [n..] 
with  [n..] = enumFrom n , a possible
 enumFrom :: a -> [a] 
 (>) :: a -> a -> Bool  implementation being  enumFrom n = n :
( infix 4 ) enumFrom (succ n) .
 (>=) :: a -> a -> Bool  Used in Haskell’s translation of  [n,n'..] 
( infix 4 ) with  [n,n'..] = enumFromThen n n' , a
possible implementation being
 max :: a -> a -> a   enumFromThen :: a -> a -> [a] 
`enumFromThen n n’ = n : n’ : worker (f x)
 min :: a -> a -> a  (f x n’), worker s v = v : worker s (s v), x =
fromEnum n’ - fromEnum n and f n y

Used in Haskell’s translation of  [n..m] 


 class Enum a where  with  [n..m] = enumFromTo n m , a
 enumFromTo :: a -> a -> [a] 
possible implementation being
Class  Enum  defines operations on sequentially ordered types. `enumFromTo n m

The  enumFrom … methods are used in Haskell’s translation of arithmetic sequences. Used in Haskell’s translation of
 [n,n'..m]  with  [n,n'..m] =
Instances of  Enum  may be derived for any enumeration type (types whose constructors enumFromThenTo n n' m , a possible
 enumFromThenTo :: a -> a -> a ->
have no fields). The nullary constructors are assumed to be numbered left-to-right by implementation being `enumFromThenTo
[a] 
 fromEnum  from  0  through  n-1 . n n’ m = worker (f x) (c x) n m, x =
fromEnum n’ - fromEnum n, c x = bool (>=)
For any type that is an instance of class  Bounded  as well as  Enum , the following should ((x 0) f n y
hold: The calls  succ maxBound  and  pred minBound  should result in a runtime error.
 fromEnum  and  toEnum  should give a runtime error if the result value is not representable in
the result type. For example,  toEnum 7 :: Bool  is an error.  enumFrom  and  enumFromThen 
should be defined with an implicit bound.

Minimal complete definition:  toEnum, fromEnum 


Numeric types
 class Bounded a where 
The  Bounded  class is used to name the upper and lower limits of a type.  Ord  is not a  data Int 
superclass of  Bounded  since types that are not totally ordered may also have upper and
lower bounds. A fixed-precision integer type with at least the range  [-2^29 .. 2^29-1] . The exact range
for a given implementation can be determined by using  minBound  and  maxBound  from the
The  Bounded  class may be derived for any enumeration type;  minBound  is the first
 Bounded  class.
constructor listed in the data declaration and  maxBound  is the last.  Bounded  may also be
derived for single-constructor datatypes whose constituent types are in  Bounded . Instances:  Bounded ,  Enum ,  Num ,  Read ,  Integral ,  Real ,  Show ,  Eq ,  Ord 

Signature Docs
 data Integer 
 minBound :: a 

 maxBound :: a  Arbitrary precision integers. In contrast with fixed-size integral types such as  Int , the
 Integer  type represents the entire infinite range of integers.

Integers are stored in a kind of sign-magnitude form, hence do not expect two’s complement
form when using bit operations.

Instances:  Enum ,  Num ,  Read ,  Integral ,  Real ,  Show ,  Eq ,  Ord 

 data Float 
Single-precision floating point numbers. It is desirable that this type be at least equal in
range and precision to the IEEE single-precision type.

Instances:  Enum ,  Floating ,  RealFloat ,  Num ,  Read ,  Fractional ,  Real ,  RealFrac ,


 Show ,  Eq ,  Ord 

 data Double 
Double-precision floating point numbers. It is desirable that this type be at least equal in
range and precision to the IEEE double-precision type.

Instances:  Enum ,  Floating ,  RealFloat ,  Num ,  Read ,  Fractional ,  Real ,  RealFrac ,


 Show ,  Eq ,  Ord 

 type Rational = Ratio Integer 


Arbitrary-precision rational numbers, represented as a ratio of two  Integer  values. A
rational number may be constructed using the  %  operator.
Signature Docs
Numeric type classes
 (+) :: a -> a -> a 
( infixl 6 )
 class Num a where   (-) :: a -> a -> a 
( infixl 6 )
Basic numeric class.
 (*) :: a -> a -> a 
The Haskell Report defines no laws for  Num . However,  (+)  and  (*)  are customarily ( infixl 7 )
expected to define a ring and have the following properties:
 negate :: a -> a  Unary negation.
Associativity of  (+) :  (x + y) + z = x + (y + z) 
 abs :: a -> a  Absolute value.
Commutativity of  (+) :  x + y = y + x 
 fromInteger 0  is the additive identity:  x + fromInteger 0 = x  Sign of a number. The functions  abs  and
 signum  should satisfy the law: abs x *
 negate  gives the additive inverse:  x + negate x = fromInteger 0 
 signum :: a -> a  signum x == x .
Associativity of  (*) :  (x * y) * z = x * (y * z)  For real numbers, the  signum  is either
 fromInteger 1  is the multiplicative identity:  x * fromInteger 1 = x  and  -1  (negative),  0  (zero) or  1  (positive).
 fromInteger 1 * x = x 
Conversion from an  Integer . An integer
Distributivity of  (*)  with respect to  (+) :  a * (b + c) = (a * b) + (a * c)  and  (b
+ c) * a = (b * a) + (c * a)  literal represents the application of the
 fromInteger :: Integer -> a  function  fromInteger  to the appropriate
Coherence with  toInteger : if the type also implements  Integral , then  fromInteger  value of type  Integer , so such literals
is a left inverse for  toInteger , i.e.  fromInteger (toInteger i) == i  have type  (Num a) => a .
Note that it isn’t customarily expected that a type instance of both  Num  and  Ord  implement
an ordered ring. Indeed, in base only  Integer  and  Rational  do.
 class (Num a, Ord a) => Real a where 
Minimal complete definition:  (+), (*), abs, signum, fromInteger, (negate | (-)) 
Real numbers.

The Haskell report defines no laws for  Real , however  Real  instances are customarily
expected to adhere to the following law:

Coherence with  fromRational : if the type also implements  Fractional , then


 fromRational  is a left inverse for  toRational , i.e.  fromRational (toRational i) = i .

Signature Docs

the rational equivalent of its real argument


 toRational :: a -> Rational 
with full precision
 class (Real a, Enum a) => Integral a where   class Num a => Fractional a where 
Integral numbers, supporting integer division. Fractional numbers, supporting real division.

The Haskell Report defines no laws for  Integral . However,  Integral  instances are The Haskell Report defines no laws for  Fractional . However,  (+)  and  (*)  are
customarily expected to define a Euclidean domain and have the following properties for the customarily expected to define a division ring and have the following properties:
 div / mod  and  quot / rem  pairs, given suitable Euclidean functions  f  and  g :
recip gives the multiplicative inverse:  x * recip x = recip x * x = fromInteger 1 
 x = y * quot x y + rem x y  with  rem x y = fromInteger 0  or  g (rem x y) < g Totality of  toRational :  toRational  is total

Coherence with  toRational : if the type also implements  Real , then  fromRational  is
 x = y * div x y + mod x y  with  mod x y = fromInteger 0  or  f (mod x y) < f y  a left inverse for  toRational , i.e.  fromRational (toRational i) = i 

An example of a suitable Euclidean function, for Integer’s instance, is  abs . Note that it isn’t customarily expected that a type instance of  Fractional  implement a
field. However, all instances in base do.
In addition,  toInteger  should be total, and  fromInteger  should be a left inverse for it, i.e.
 fromInteger (toInteger i) = i . Minimal complete definition:  fromRational, (recip | (/)) 

Minimal complete definition:  quotRem, toInteger 


Signature Docs

Signature Docs  (/) :: a -> a -> a  ( infixl 7 ) Fractional division.

 quot :: a -> a -> a  ( infixl 7 ) integer division truncated toward zero  recip :: a -> a  Reciprocal fraction.

integer remainder, satisfying  (x `quot` Conversion from a  Rational  (that is 
 rem :: a -> a -> a  ( infixl 7 )
y)*y + (x `rem` y) == x  Ratio Integer ). A floating literal stands
 fromRational :: Rational -> a  for an application of  fromRational  to a
integer division truncated toward negative value of type  Rational , so such literals
 div :: a -> a -> a  ( infixl 7 )
infinity have type  (Fractional a) => a .
integer modulus, satisfying  (x `div`
 mod :: a -> a -> a  ( infixl 7 )
y)*y + (x `mod` y) == x 

 quotRem :: a -> a -> (a, a)  simultaneous  quot  and  rem 

 divMod :: a -> a -> (a, a)  simultaneous  div  and  mod 

 toInteger :: a -> Integer  conversion to Integer

⚠️ The functions  quot ,  rem ,  div ,  mod ,  quotRem  and  divMod  are partial (because they
throw when  0  is passed as the divisor) for all the integer types in base.
 class Fractional a => Floating a where   class (Real a, Fractional a) => RealFrac a where 
Trigonometric and hyperbolic functions and related functions. Extracting components of fractions.

The Haskell Report defines no laws for  Floating . However,  (+) ,  (*)  and  exp  are Minimal complete definition:  properFraction 
customarily expected to define an exponential field and have the following properties:  exp
(a + b) = exp a * exp b ,  exp (fromInteger 0) = fromInteger 1  Signature Docs

Minimal complete definition:  pi, exp, log, sin, cos, asin, acos, atan, sinh, cosh, The function  properFraction  takes a
asinh, acosh, atanh  real fractional number  x  and returns a
pair  (n,f)  such that  x = n+f , and:  n  is
Signature Docs an integral number with the same sign as
 properFraction :: Integral b => a ->  x ; and  f  is a fraction with the same type
 pi :: a  (b, a)  and sign as  x , and with absolute value
less than  1 .
 exp :: a -> a 
The default definitions of the  ceiling ,
 log :: a -> a   floor ,  truncate  and  round  functions
are in terms of properFraction.
 sqrt :: a -> a 
 truncate x  returns the integer nearest
 (**) :: a -> a -> a   truncate :: Integral b => a -> b 
 x  between zero and  x 
( infixr 8 )
 round x  returns the nearest integer to
 logBase :: a -> a -> a   round :: Integral b => a -> b   x ; the even integer if  x  is equidistant
between two integers
 sin :: a -> a 

 cos :: a -> a   ceiling x  returns the least integer not


 ceiling :: Integral b => a -> b 
less than  x 
 tan :: a -> a 
 floor x  returns the greatest integer not
 floor :: Integral b => a -> b 
 asin :: a -> a  greater than  x 

 acos :: a -> a 

 atan :: a -> a 

 sinh :: a -> a 

 cosh :: a -> a 

 tanh :: a -> a 

 asinh :: a -> a 

 acosh :: a -> a 

 atanh :: a -> a 
Signature Docs
 class (RealFrac a, Floating a) => RealFloat a  floatRadix :: a -> Integer 
a constant function, returning the radix of
the representation (often  2 )
where 
a constant function, returning the number
 floatDigits :: a -> Int 
of digits of  floatRadix  in the significand
Efficient, machine-independent access to the components of a floating-point number.
a constant function, returning the lowest
Minimal complete definition:  floatRadix, floatDigits, floatRange, decodeFloat,
 floatRange :: a -> (Int, Int)  and highest values the exponent may
encodeFloat, isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE 
assume

The function  decodeFloat  applied to a


real floating-point number returns the
significand expressed as an  Integer  and
an appropriately scaled exponent (an
 Int ). If  decodeFloat x  yields  (m,n) ,
then  x  is equal in value to  m*b^^n ,
where  b  is the floating-point radix, and
 decodeFloat :: a -> (Integer, Int)  furthermore, either  m  and  n  are both
zero or else  b^(d-1) <= abs m < b^d ,
where  d  is the value of  floatDigits x .
In particular,  decodeFloat 0 = (0,0) . If
the type contains a negative zero, also
 decodeFloat (-0.0) = (0,0) . The result
of  decodeFloat x  is unspecified if either
of  isNaN x  or  isInfinite x  is  True .

 encodeFloat  performs the inverse of


 decodeFloat  in the sense that for finite
 x  with the exception of  -0.0 ,  uncurry
encodeFloat (decodeFloat x) = x .
 encodeFloat m n  is one of the two
 encodeFloat :: Integer -> Int -> a 
closest representable floating-point
numbers to  m*b^^n  (or ± Infinity  if
overflow occurs); usually the closer, but if
 m  contains too many bits, the result may
be rounded in the wrong direction.

 exponent  corresponds to the second


component of  decodeFloat .  exponent 0
= 0  and for finite nonzero  x ,  exponent
x = snd (decodeFloat x) + floatDigits
 exponent :: a -> Int  x . If  x  is a finite floating-point number, it
is equal in value to significand  x * b ^^
exponent x , where  b  is the floating-point
radix. The behaviour is unspecified on
infinite or NaN values.
Signature Docs
Numeric functions
The first component of  decodeFloat ,
scaled to lie in the open interval  (-1,1) , Signature Docs
either  0.0  or of absolute value  >= 1/b ,
 significand :: a -> a  the same as  flip (-) .
where  b  is the floating-point radix. The
Because  -  is treated specially in the
behaviour is unspecified on infinite or NaN
Haskell grammar,  (- e)  is not a section,
values.  subtract :: Num a => a -> a -> a 
but an application of prefix negation.
multiplies a floating-point number by an However,  (subtract exp)  is equivalent
 scaleFloat :: Int -> a -> a  to the disallowed section.
integer power of the radix

 True  if the argument is an IEEE “not-a-  even :: Integral a => a -> Bool 
 isNaN :: a -> Bool 
number” (NaN) value
 odd :: Integral a => a -> Bool 
 True  if the argument is an IEEE infinity or
 isInfinite :: a -> Bool   gcd x y  is the non-negative factor of
negative infinity
both  x  and  y  of which every common
 True  if the argument is too small to be factor of  x  and  y  is also a factor; for
 isDenormalized :: a -> Bool  example  gcd 4 2 = 2 ,  gcd (-4) 6 = 2 ,
represented in normalized format
 gcd 0 4 = 4 .  gcd 0 0 = 0 . (That is, the
 True  if the argument is an IEEE negative common divisor that is “greatest” in the
 isNegativeZero :: a -> Bool   gcd :: Integral a => a -> a -> a 
zero divisibility preordering.)
 True  if the argument is an IEEE floating Note: Since for signed fixed-width integer
 isIEEE :: a -> Bool  types,  abs minBound < 0 , the result may
point number
be negative if one of the arguments is
a version of arctangent taking two real  minBound  (and necessarily is if the other
floating-point arguments. For real floating is  0  or  minBound ) for such types.
 x  and  y ,  atan2 y x  computes the
angle (from the positive x-axis) of the  lcm x y  is the smallest positive integer
 lcm :: Integral a => a -> a -> a 
vector from the origin to the point  (x,y) . that both  x  and  y  divide.
 atan2 y x  returns a value in the range  (^) :: (Num a, Integral b) => a -> b raise a number to a non-negative integral
 [-pi, pi] . It follows the Common Lisp -> a infixr 8  power
 atan2 :: a -> a -> a 
semantics for the origin when signed
zeroes are supported.  atan2 y 1 , with  (^^) :: (Fractional a, Integral b)
raise a number to an integral power
 y  in a type that is  RealFloat , should => a -> b -> a infixr 8 
return the same value as  atan y . A
⚠️
General coercion from  Integral  types.
default definition of  atan2  is provided,
 fromIntegral :: (Integral a, Num b) This function performs silent
but implementors can provide a more
=> a -> b  truncation if the result type is not at least
accurate implementation.
as big as the argument’s type.

⚠️
General coercion to  Fractional  types.
This function goes through the
 realToFrac :: (Real a, Fractional b)  Rational  type, which does not have
=> a -> b  values for  NaN  for example. This means it
does not round-trip. For  Double  it also
behaves differently with or without  -O0 .
>>> fmap show Nothing
Monads and functors
Nothing

 class Functor f where  >>> fmap show (Just 3)


Just "3"

A type  f  is a Functor if it provides a function  fmap  which, given any types  a  and  b  lets >>> fmap show (Left 17)
you apply any function from  (a -> b)  to turn an  f a  into an  f b , preserving the Left 17
structure of  f . Furthermore  f  needs to adhere to the following:
>>> fmap show (Right 17)
Identity:  fmap id == id  Right "17"
Composition:  fmap (f . g) == fmap f . fmap g 
>>> fmap (*2) [1,2,3]
Note, that the second law follows from the free theorem of the type  fmap  and the first law, [2,4,6]
so you need only check that the former condition holds.
>>> fmap even (2,2)
Minimal complete definition:  fmap 
(2,True)

Signature Docs >>> fmap even ("hello", 1.0, 4)


("hello",1.0,True)
 fmap  is used to apply a function of type
 (a -> b)  to a value of type  f a , where
>>> 'a' <$ Just 2
 f  is a functor, to produce a value of type
Just 'a'
 f b . Note that for any type constructor
with more than one parameter (e.g.,
>>> 'a' <$ Nothing
 Either ), only the last type parameter can
Nothing
 fmap :: (a -> b) -> f a -> f b  be modified with fmap (e.g.,  b  in  Either
a b ).
Some type constructors with two
Signature Docs
parameters or more have a  Bifunctor 
instance that allows both the last and the An infix synonym for  fmap . The name of
penultimate parameters to be mapped  (<$>) :: Functor f => (a -> b) -> f
this operator is an allusion to  $ . Whereas
over. a -> f b 
 $  is function application,  <$>  is
( infixl 4 )
function application lifted over a Functor.
Replace all locations in the input with the
 (<$) :: a -> f b -> f a  same value. The default definition is  fmap
( infixl 4 ) . const , but this may be overridden with
a more efficient version.
Signature Docs
 class Functor f => Applicative f where   pure :: a -> f a  Lift a value.

Sequential application.
A functor with application, providing operations to embed pure expressions ( pure ), and  (<*>) :: f (a -> b) -> f a -> f b  A few functors support an implementation
sequence computations and combine their results ( <*>  and  liftA2 ). ( infixl 4 ) of  <*>  that is more efficient than the
default one.
A minimal complete definition must include implementations of  pure  and of either  <*>  or
 liftA2 . If it defines both, then they must behave the same as their default definitions: Lift a binary function to actions.
 (<*>) = liftA2 id ,  liftA2 f x y = f <$> x <*> y  Some functors support an implementation
of  liftA2  that is more efficient than the
Further, any definition must satisfy the following:  liftA2 :: (a -> b -> c) -> f a -> f
default one. In particular, if  fmap  is an
b -> f c 
Identity:  pure id <*> v = v  expensive operation, it is likely better to
use  liftA2  than to  fmap  over the
Composition:  pure (.) <*> u <*> v <*> w = u <*> (v <*> w) 
structure and then use  <*> .
Homomorphism:  pure f <*> pure x = pure (f x) 
Interchange:  u <*> pure y = pure ($ y) <*> u   (*>) :: f a -> f b -> f b  Sequence actions, discarding the value of
( infixl 4 ) the first argument.
The other methods have the following default definitions, which may be overridden with
 (<*) :: f a -> f b -> f a  Sequence actions, discarding the value of
equivalent specialized implementations:  u *> v = (id <$ u) <*> v ,  u <* v = liftA2
( infixl 4 ) the second argument.
const u v 

As a consequence of these laws, the  Functor  instance for  f  will satisfy  fmap f x = pure
f <*> x  >>> data MyState = MyState {arg1 :: Foo, arg2 :: Bar, arg3 :: Baz}
>>> produceFoo :: Applicative f => f Foo
It may be useful to note that supposing  forall x y. p (q x y) = f x . g y  it follows >>> produceBar :: Applicative f => f Bar
from the above that  liftA2 p (liftA2 q u v) = liftA2 f u . liftA2 g v  >>> produceBaz :: Applicative f => f Baz
>>> mkState :: Applicative f => f MyState
If  f  is also a  Monad , it should satisfy  pure = return ,  m1 <*> m2 = m1 >>= (\x1 -> m2 >>> mkState = MyState <$> produceFoo <*> produceBar <*> produceBaz
>>= (\x2 -> return (x1 x2))) ,  (*>) = (>>)  (which implies that  pure  and  <*>  satisfy
the applicative functor laws). >>> liftA2 (,) (Just 3) (Just 5)
Just (3,5)
Minimal complete definition:  pure, ((<*>) | liftA2) 
>>> Just 2 *> Just 3
Just 3

>>> Nothing *> Just 3


Nothing

>>> import Data.Char


>>> import Text.ParserCombinators.ReadP
>>> let p = string "my name is " *> munch1 isAlpha <* eof
>>> readP_to_S p "my name is Simon"
[("Simon","")]
Folds and traversals
 class Applicative m => Monad m where 
The  Monad  class defines the basic operations over a monad, a concept from a branch of  class Foldable t where 
mathematics known as category theory. From the perspective of a Haskell programmer,
however, it is best to think of a monad as an abstract datatype of actions. Haskell’s  do  The  Foldable  class represents data structures that can be reduced to a summary value
expressions provide a convenient syntax for writing monadic expressions. one element at a time. Strict left-associative folds are a good fit for space-efficient
reduction, while lazy right-associative folds are a good fit for corecursive iteration, or for
Instances of  Monad  should satisfy the following:
folds that short-circuit after processing an initial subsequence of the structure’s elements.
Left identity:  return a >>= k = k a 
Instances can be derived automatically by enabling the  DeriveFoldable  extension.
Right identity:  m >>= return = m 
Associativity:  m >>= (\x -> k x >>= h) = (m >>= k) >>= h  Left and right folds

Furthermore, the  Monad  and  Applicative  operations should relate as follows:  pure = The contribution of each element to the final result is combined with an accumulator via a
return ,  m1 <*> m2 = m1 >>= (\x1 -> m2 >>= (\x2 -> return (x1 x2)))  suitable operator. The operator may be explicitly provided by the caller as with  foldr  or
may be implicit as in  length . In the case of  foldMap , the caller provides a function
The above laws imply:  fmap f xs = xs >>= return . f ,  (>>) = (*>)  and that  pure  and mapping each element into a suitable  Monoid , which makes it possible to merge the per-
 (<*>)  satisfy the applicative functor laws. element contributions via that monoid’s  mappend  function.
The instances of Monad for lists,  Maybe  and  IO  defined in the Prelude satisfy these laws. A key distinction is between left-associative and right-associative folds:
Minimal complete definition:  (>>=)  In left-associative folds the accumulator is a partial fold over the elements that precede
the current element, and is passed to the operator as its first (left) argument. The
Signature Docs outermost application of the operator merges the contribution of the last element of the
structure with the contributions of all its predecessors.
Sequentially compose two actions,
passing any value produced by the first as In right-associative folds the accumulator is a partial fold over the elements that follow
 (>>=) :: forall a b. m a -> (a -> m the current element, and is passed to the operator as its second (right) argument. The
an argument to the second.
b) -> m b  outermost application of the operator merges the contribution of the first element of the
 as >>= bs  can be understood as the  do 
( infixl 1 ) structure with the contributions of all its successors.
expression
 do { a <- as; bs a } 
Recursive and corecursive reduction
Sequentially compose two actions,
discarding any value produced by the first, As observed in the above description of left and right folds, there are three general ways in
 (>>) :: forall a b. m a -> m b -> m
like sequencing operators (such as the which a structure can be reduced to a summary value:

semicolon) in imperative languages.  as
( infixl 1 ) Recursive reduction, which is strict in all the elements of the structure. This produces a
>> bs  can be understood as the  do 
expression  do { as; bs }  single final result only after processing the entire input structure, and so the input must
be finite.
 return :: a -> m a  Inject a value into the monadic type. Corecursion, which yields intermediate results as it encounters additional input
elements. Lazy processing of the remaining elements makes the intermediate results
available even before the rest of the input is processed. The input may be unbounded,
and the caller can stop processing intermediate results early.
Short-circuit reduction, which examines some initial sequence of the input elements,
but stops once a termination condition is met, returning a final result based only on the
elements considered up to that point. The remaining elements are not considered. The
input should generally be finite, because the termination condition might otherwise
never be met.
Whether a fold is recursive, corecursive or short-circuiting can depend on both the method Signature Docs
chosen to perform the fold and on the operator passed to that method (which may be
implicit, as with the  mappend  method of a monoid instance). Map each element of the structure into a
monoid, and combine the results with
Strict recursive folds  foldMap :: Monoid m => (a -> m) -> t  (<>) . This fold is right-associative and
a -> m  lazy in the accumulator. For strict left-
Common examples of strict recursive reduction are the various aggregate functions, like associative folds consider  foldMap' 
 sum ,  product ,  length , as well as more complex summaries such as frequency counts. instead.
These functions return only a single value after processing the entire input structure. In such
cases, lazy processing of the tail of the input structure is generally not only unnecessary, but Right-associative fold of a structure, lazy
also inefficient. Thus, these and similar folds should be implemented in terms of strict left- in the accumulator.
associative  Foldable  methods (typically  foldl' ) to perform an efficient reduction in In the case of lists, foldr, when applied to
constant space. a binary operator, a starting value
(typically the right-identity of the
Lazy corecursive folds operator), and a list, reduces the list using
the binary operator, from right to left:
Common examples of lazy corecursive reduction are functions that map and flatten a  foldr f z [x1, x2, ..., xn] == x1
structure to a lazy stream of result values, like  toList ,  concat  and  concatMap , i.e. an `f` (x2 `f` ... (xn `f` z)...) 
iterator over the transformed input elements. In such cases, it is important to choose a Note that since the head of the resulting
 Foldable  method that is lazy in the tail of the structure, such as  foldr  (or  foldMap , if the expression is produced by an application
result  Monoid  has a lazy  mappend  as with e.g.  ByteString  Builders). of the operator to the first element of the
 foldr :: (a -> b -> b) -> b -> t a -
list, given an operator lazy in its right
> b 
Short-circuit folds argument,  foldr  can produce a
terminating expression from an
Examples of short-circuit reduction include various boolean predicates that test whether unbounded list.
some or all the elements of a structure satisfy a given condition, like  null ,  elem ,  and , For a general Foldable structure this
 find ,  any . Because these don’t necessarily consume the entire list, they typically employ should be semantically identical to:  foldr
 foldr  with an operator that is conditionally strict in its second argument. Once the
⚠️
f z = foldr f z . toList 
termination condition is met the second argument (tail of the input structure) is ignored. No Applying  foldr  to infinite structures
result is returned until that happens. The key distinguishing feature of these folds is usually doesn’t terminate. It may still
conditional strictness in the second argument, it is sometimes evaluated and sometimes terminate under one of the following
not. conditions: the folding function is short-
circuiting; the folding function is lazy on
Minimal complete definition:  foldMap | foldr  its second argument
Signature Docs Signature Docs

Left-associative fold of a structure, lazy in The largest element of a non-empty


the accumulator. This is rarely what you structure.
want, but can work well for structures with This function is non-total and will raise a
efficient right-to-left sequencing and an runtime exception if the structure happens
 maximum :: forall a. Ord a => t a ->
operator that is lazy in its left argument. to be empty. A structure that supports

In the case of lists,  foldl , when applied random access and maintains its
to a binary operator, a starting value elements in order should provide a
(typically the left-identity of the operator), specialised implementation to return the
and a list, reduces the list using the binary maximum in faster than linear time.
operator, from left to right:  foldl f z
[x1, x2, ..., xn] == (...((z `f` x1) The least element of a non-empty
`f` x2) `f`...) `f` xn  structure.
Note that to produce the outermost This function is non-total and will raise a
application of the operator the entire input runtime exception if the structure happens
 minimum :: forall a. Ord a => t a ->
list must be traversed. Like all left- to be empty. A structure that supports

 foldl :: (b -> a -> b) -> b -> t a - associative folds,  foldl  will diverge if random access and maintains its
> b  given an infinite list. elements in order should provide a
If you want an efficient strict left-fold, you specialised implementation to return the
probably want to use  foldl'  instead of minimum in faster than linear time.
 foldl . The reason for this is that the The  sum  function computes the sum of
latter does not force the inner results (e.g.  sum :: Num a => t a -> a 
the numbers of a structure.
 z `f` x1  in the above example) before
applying them to the operator (e.g. to The  product  function computes the
 product :: Num a => t a -> a 
 (`f` x2) ). This results in a thunk chain product of the numbers of a structure.
O(n) elements long, which then must be
evaluated from the outside-in.
For a general  Foldable  structure this
should be semantically identical to:  foldl

⚠️
f z = foldl f z . toList 
When it comes to lists, you always
want to use either  foldl'  or  foldr 
instead.

A variant of  foldr  that has no base case,


and thus may only be applied to non-
empty structures.
 foldr1 :: (a -> a -> a) -> t a -> a 
This function is non-total and will raise a
runtime exception if the structure happens
to be empty.

A variant of  foldl  that has no base case,


and thus may only be applied to non-
empty structures.
 foldl1 :: (a -> a -> a) -> t a -> a  This function is non-total and will raise a
runtime exception if the structure happens
to be empty.
 foldl1 f = foldl1 f . toList 

 elem :: Eq a => a -> t a -> Bool  Does the element occur in the structure?
( infix 4 ) Note:  elem  is often used in infix form.
>>> foldMap Sum [1, 3, 5] >>> foldr1 (+) [1..]
Sum {getSum = 9} -- * Hangs forever *

>>> foldMap (replicate 3) [1, 2, 3] >>> 3 `elem` [1..]


[1,1,1,2,2,2,3,3,3] True

>>> foldr (||) False [False, True, False] >>> 3 `elem` ([4..] ++ [3])
True -- * Hangs forever *

>>> foldr (||) False [] >>> maximum []


False *** Exception: Prelude.maximum: empty list

>>> foldr (\c acc -> acc ++ [c]) "foo" ['a', 'b', 'c', 'd'] >>> maximum Nothing
"foodcba" *** Exception: maximum: empty structure

-- short circuiting
>>> foldr (||) False (True : repeat False)
True

>>> foldr (||) False (repeat False ++ [True])


-- * Hangs forever *

-- laziness in the second argument


>>> take 5 $ foldr (\i acc -> i : fmap (+3) acc) [] (repeat 1)
[1,4,7,10,13]

>>> foldl (+) 42 [1,2,3,4]


52 -- (((42 + 1) + 2) + 3) + 4

>>> foldl (\acc c -> c : acc) "abcd" "efgh"


"hgfeabcd"

>>> foldl (\a _ -> a) 0 $ repeat 1


-- * Hangs forever *

>>> foldr1 (+) [1..4]


10 -- 1 + (2 + (3 + 4))

>>> foldr1 (+) []


Exception: Prelude.foldr1: empty list

>>> foldr1 (+) Nothing


*** Exception: foldr1: empty structure

>>> foldr1 (-) [1..4]


-2 -- 1 - (2 - (3 - 4))

>>> foldr1 (&&) [True, False, True, True]


False

>>> foldr1 (||) [False, False, True, True]


True
Miscellaneous functions Signature Docs
Signature Docs The value of  seq a b  is bottom if  a  is
bottom, and otherwise equal to  b . In
Identity function.
 id :: a -> a  other words, it evaluates the first
 id x = x 
argument  a  to weak head normal form
 const x y  always evaluates to  x , (WHNF).  seq  is usually introduced to
 const :: a -> b -> a  improve performance by avoiding
ignoring its second argument.
unneeded laziness.
 (.) :: (b -> c) -> (a -> b) -> a ->  seq :: forall {r :: RuntimeRep} a (b A note on evaluation order: the expression
c  Function composition. :: TYPE r). a -> b -> b   seq a b  does not guarantee that  a  will
( infixr 9 ) ( infixr 0 ) be evaluated before  b . The only
guarantee given by  seq  is that the both
 flip :: (a -> b -> c) -> b -> a ->  flip f  takes its (first) two arguments in
 a  and  b  will be evaluated before  seq 
c  the reverse order of  f .
returns a value. In particular, this means
Application operator. This operator is that  b  may be evaluated before  a . If you
redundant, since ordinary application ( f need to guarantee  a  specific order of
x ) means the same as ( f $ x ). However, evaluation, you must use the function
 $  has low, right-associative binding  pseq  from the “parallel” package.
precedence, so it sometimes allows
Strict (call-by-value) application operator.
 ($) :: forall r a (b :: TYPE r). (a parentheses to be omitted.
 ($!) :: forall r a (b :: TYPE r). (a It takes a function and an argument,
-> b) -> a -> b  It is also useful in higher-order situations,
-> b) -> a -> b  evaluates the argument to weak head
( infixr 0 ) such as  map ($ 0) xs , or  zipWith ($)
( infixr 0 ) normal form (WHNF), then calls the
fs xs .
function with that value.
Note that  ($)  is representation-
polymorphic in its result type, so that  foo
$ True  where  foo :: Bool -> Int#  is
well-typed.

 until :: (a -> Bool) -> (a -> a) ->  until p f  yields the result of applying
a -> a   f  until  p  holds.

 asTypeOf  is a type-restricted version of


 const . It is usually used as an infix
 asTypeOf :: a -> a -> a  operator, and its typing forces its first
argument (which is usually overloaded) to
have the same type as the second.

 error :: forall (r :: RuntimeRep).


 error  stops execution and displays an
forall (a :: TYPE r). HasCallStack =>
error message.
[Char] -> a 

 errorWithoutStackTrace :: forall (r
A variant of  error  that does not produce
:: RuntimeRep). forall (a :: TYPE r).
a stack trace.
[Char] -> a 

A special case of  error . It is expected


 undefined :: forall (r :: that compilers will recognize this and
RuntimeRep). forall (a :: TYPE r). insert error messages which are more
HasCallStack => a  appropriate to the context in which
 undefined  appears.
List operations Signature Docs
Signature Docs Returns the size/length of a finite
structure as an  Int . The default
O(n).  map f xs  is the list obtained by
 map :: (a -> b) -> [a] -> [b]  implementation just counts elements
applying  f  to each element of  xs .
starting with the leftmost. Instances for
 length :: Foldable t => t a -> Int 
Append two lists. If the first list is not structures that can compute the element
count faster than via element-by-element
⚠️
 (++) :: [a] -> [a] -> [a]  finite, the result is the first list.
( infixr 5 ) This function takes linear time in the counting, should provide a specialised
number of elements of the first list. implementation.

O(n).  filter , applied to a predicate and  reverse xs  returns the elements of  xs 
 reverse :: [a] -> [a] 
 filter :: (a -> Bool) -> [a] -> [a]  a list, returns the list of those elements in reverse order.  xs  must be finite.
that satisfy the predicate.

O(1). Extract the first element of a list,

⚠️
which must be non-empty.
 head :: HasCallStack => [a] -> a  This function is partial. You can use
case-matching,  uncons  or  listToMaybe 
instead.

O(n). Extract the last element of a list,

⚠️
which must be finite and non-empty.
 last :: HasCallStack => [a] -> a  This function is partial. You can use
 reverse  with case-matching,  uncons  or
 listToMaybe  instead.

O(1). Extract the elements after the head

⚠️
of a list, which must be non-empty.
 tail :: HasCallStack => [a] -> [a] 
This function is partial. You can use
case-matching or  uncons  instead.

O(n). Return all the elements of a list


except the last one. The list must be non-

⚠️
empty.
 init :: HasCallStack => [a] -> [a] 
This function is partial. You can use
 reverse  with case-matching or  uncons 
instead.

List index (subscript) operator, starting


from  0 . It is an instance of the more
 (!!) :: HasCallStack => [a] -> Int -
general  genericIndex , which takes an
> a 
⚠️
index of any integral type.
( infixl 9 )
This function is partial. You can use
 atMay  instead.

Test whether the structure is empty. The


default implementation is Left-associative
and lazy in both the initial element and the
accumulator. Thus optimised for
 null :: Foldable t => t a -> Bool 
structures where the first element can be
accessed in constant time. Structures
where this is not the case should have a
non-default implementation.
3
>>> map (+1) [1, 2, 3]
[2,3,4] >>> length [1..]
-- * Hangs forever *
>>> filter odd [1, 2, 3]
[1,3] >>> reverse []
[]
>>> head [1..]
1 >>> reverse [42]
[42]
>>> head []
*** Exception: Prelude.head: empty list >>> reverse [1..]
-- * Hangs forever *
>>> last [1..]
-- * Hangs forever *

>>> last []
*** Exception: Prelude.last: empty list

>>> tail [1, 2, 3]


[2,3]

>>> tail [1]


[]

>>> tail []
*** Exception: Prelude.tail: empty list

>>> init [1, 2, 3]


[1,2]

>>> init [1]


[]

>>> init []
*** Exception: Prelude.init: empty list

>>> ['a', 'b', 'c'] !! 0


'a'

>>> ['a', 'b', 'c'] !! 2


'c'

>>> ['a', 'b', 'c'] !! 3


*** Exception: Prelude.!!: index too large

>>> ['a', 'b', 'c'] !! (-1)


*** Exception: Prelude.!!: negative index

>>> null []
True

>>> length ['a', 'b', 'c']


>>> and []
Special folds
True
Signature Docs
>>> and [True]
 and  returns the conjunction of a True
container of Bools. For the result to be
 and :: Foldable t => t Bool -> Bool   True , the container must be finite; >>> and [False]
 False , however, results from a  False  False
value finitely far from the left end.
>>> and [True, True, False]
 or  returns the disjunction of a container False
of Bools. For the result to be  False , the
 or :: Foldable t => t Bool -> Bool  container must be finite;  True , however, >>> and (False : repeat True) -- Infinite list [False,True,True,True,...
results from a  True  value finitely far from False
the left end.

 any :: Foldable t => (a -> Bool) -> Determines whether any element of the >>> and (repeat True)
t a -> Bool  structure satisfies the predicate. -- * Hangs forever *

 all :: Foldable t => (a -> Bool) -> Determines whether all elements of the >>> or [False]
t a -> Bool  structure satisfy the predicate. False

 concat :: Foldable t => t [a] -> The concatenation of all the elements of a >>> or [True, True, False]
[a]  container of lists. True
Map a function over all the elements of a
 concatMap :: Foldable t => (a -> >>> any (> 3) [1,2]
container and concatenate the resulting
[b]) -> t a -> [b]  False
lists.
>>> any (> 3) [1,2,3,4,5]
True

>>> all (> 3) [1,2,3,4,5]


False

>>> concat (Just [1, 2, 3])


[1,2,3]

>>> concat (Left 42)


[]

>>> concat [[1, 2, 3], [4, 5], [6], []]


[1,2,3,4,5,6]

>>> concatMap (take 3) [[1..], [10..], [100..], [1000..]]


[1,2,3,10,11,12,100,101,102,1000,1001,1002]

>>> concatMap (take 3) (Just [1..])


[1,2,3]
Building lists
>>> scanl (+) 0 [1..4]
Signature Docs [0,1,3,6,10]

O(n).  scanl  is similar to  foldl , but >>> scanl (+) 42 []


returns a list of successive reduced [42]
 scanl :: (b -> a -> b) -> b -> [a] -
values from the left:  scanl f z [x1, x2,
> [b] 
...] == [z, z `f` x1, (z `f` x1) `f` >>> scanl (+) 0 [1..]
x2, ...]  -- * Hangs forever *
O(n).  scanl1  is a variant of  scanl  that
>>> scanl1 (+) [1..4]
 scanl1 :: (a -> a -> a) -> [a] -> has no starting value argument:  scanl1 f
[1,3,6,10]
[a]  [x1, x2, ...] == [x1, x1 `f` x2,
...]  >>> scanr (-) 100 [1..4]
O(n).  scanr  is the right-to-left dual of [98,-97,99,-96,100]
 scanr :: (a -> b -> b) -> b -> [a] -  scanl . Note that the order of parameters
> [b]  on the accumulating function are reversed scanr1 (-) [1..4]
compared to  scanl . [-2,3,-1,4]

 scanr1 :: (a -> a -> a) -> [a] -> O(n).  scanr1  is a variant of  scanr  that >>> iterate (+3) 42
[a]  has no starting value argument. [42,45,48,51,54,57,60,63...

 iterate f x  returns an infinite list of >>> repeat 17


repeated applications of  f  to  x : [17,17,17,17,17,17,17,17,17...
 iterate f x == [x, f x, f (f x),
 iterate :: (a -> a) -> a -> [a]  ...] . Note that iterate is lazy, potentially >>> replicate (-1) True
leading to thunk build-up if the consumer []
doesn’t force each iterate. See  iterate' 
for a strict variant of this function. >>> replicate 4 True
[True,True,True,True]
 repeat x  is an infinite list, with  x  the
 repeat :: a -> [a] 
value of every element.
>>> cycle []
 replicate n x  is a list of length  n  with *** Exception: Prelude.cycle: empty list
 x  the value of every element. It is an
 replicate :: Int -> a -> [a]  instance of the more general >>> cycle [2, 5, 7]
 genericReplicate , in which  n  may be [2,5,7,2,5,7,2,5,7,2,5,7...
of any integral type.

 cycle  ties a finite list into a circular one,


or equivalently, the infinite repetition of
 cycle :: HasCallStack => [a] -> [a] 
the original list. It is the identity on infinite
lists.
Sublists
>>> take 3 [1,2,3,4,5]
Signature Docs [1,2,3]

 take n , applied to a list  xs , returns the >>> drop 3 [1,2]
 take :: Int -> [a] -> [a]  prefix of  xs  of length  n , or  xs  itself if []
 n >= length xs .
>>> takeWhile (< 3) [1,2,3,4,1,2,3,4]
 drop n xs  returns the suffix of  xs  after
[1,2]
 drop :: Int -> [a] -> [a]  the first  n  elements, or  []  if  n >=
length xs .
>>> dropWhile (< 3) [1,2,3,4,5,1,2,3]
 takeWhile , applied to a predicate  p  and [3,4,5,1,2,3]
 takeWhile :: (a -> Bool) -> [a] -> a list  xs , returns the longest prefix
[a]  (possibly empty) of  xs  of elements that >>> span (< 3) [1,2,3,4,1,2,3,4]
satisfy  p . ([1,2],[3,4,1,2,3,4])

 dropWhile :: (a -> Bool) -> [a] ->  dropWhile p xs  returns the suffix >>> break (> 3) [1,2,3,4,1,2,3,4]
[a]  remaining after  takeWhile p xs . ([1,2,3],[4,1,2,3,4])

 span , applied to a predicate  p  and a list >>> splitAt 3 [1,2,3,4,5]


 xs , returns a tuple where first element is ([1,2,3],[4,5])
longest prefix (possibly empty) of  xs  of
 span :: (a -> Bool) -> [a] -> ([a],
elements that satisfy  p  and second
[a]) 
element is the remainder of the list.  span Searching lists
p xs  is equivalent to  (takeWhile p xs,
dropWhile p xs) . Signature Docs
 break , applied to a predicate  p  and a  notElem :: (Foldable t, Eq a) => a -
list  xs , returns a tuple where first > t a -> Bool   notElem  is the negation of  elem .
element is longest prefix (possibly empty) ( infix 4 )
 break :: (a -> Bool) -> [a] -> ([a],
of  xs  of elements that do not satisfy  p 
[a])  O(n).  lookup key assocs  looks up a key
and second element is the remainder of  lookup :: Eq a => a -> [(a, b)] ->
the list.  break p  is equivalent to  span in an association list. For the result to be
Maybe b 
(not . p) .  Nothing , the list must be finite.

 splitAt n xs  returns a tuple where first


element is  xs  prefix of length  n  and >>> 3 `notElem` [1,2]
 splitAt :: Int -> [a] -> ([a], [a]) 
second element is the remainder of the True
list.
>>> lookup 2 [(1, "first")]
Nothing

>>> lookup 2 [(1, "first"), (2, "second"), (3, "third")]


Just "second"
Zipping and unzipping Functions on strings
Signature Docs Signature Docs

O(min(m,n)).  zip  takes two lists and Splits the argument into a list of lines
returns a list of corresponding pairs. If stripped of their terminating  \n 
one input list is shorter than the other,  lines :: String -> [String]  characters. The  \n  terminator is optional
 zip :: [a] -> [b] -> [(a, b)] 
excess elements of the longer list are in a final non-empty line of the argument
discarded, even if one of the lists is string.
infinite.  zip  is right-lazy.
 words  breaks a string up into a list of
 zip3  takes three lists and returns a list words, which were delimited by white
 zip3 :: [a] -> [b] -> [c] -> [(a, b, of triples, analogous to  zip . It is capable  words :: String -> [String]  space (as defined by  isSpace ). This
c)]  of list fusion, but it is restricted to its first function trims any white spaces at the
list argument and its resulting list. beginning and at the end.

O(min(m,n)).  zipWith  generalises  zip  Appends a  \n  character to each input


by zipping with the function given as the string, then concatenates the results.
first argument, instead of a tupling  unlines :: [String] -> String  Equivalent to  foldMap (s -> s ++
 zipWith :: (a -> b -> c) -> [a] ->
function.  zipWith  is right-lazy.  zipWith  "\n") . Note that  unlines . lines /=
[b] -> [c] 
is capable of list fusion, but it is restricted id  when the input is not  \n -terminated.
to its first list argument and its resulting
list.  unwords  joins words with separating
 unwords :: [String] -> String  spaces (U+0020 SPACE).  unwords  is
The  zipWith3  function takes a function neither left nor right inverse of  words .
which combines three elements, as well
as three lists and returns a list of the
 zipWith3 :: (a -> b -> c -> d) -> >>> lines ""
function applied to corresponding
[a] -> [b] -> [c] -> [d] 
elements, analogous to  zipWith . It is []
capable of list fusion, but it is restricted to
its first list argument and its resulting list. >>> lines "\n"
[""]
 unzip  transforms a list of pairs into a list
 unzip :: [(a, b)] -> ([a], [b])  of first components and a list of second >>> lines "one\ntwo"
components. ["one","two"]
The  unzip3  function takes a list of triples
 unzip3 :: [(a, b, c)] -> ([a], [b], >>> words "Lorem ipsum\ndolor"
and returns three lists, analogous to
[c])  ["Lorem","ipsum","dolor"]
 unzip .
>>> unlines ["Hello", "World", "!"]
"Hello\nWorld\n!\n"
>>> zip [1, 2] ['a']
[(1,'a')]
>>> unlines . lines $ "foo\nbar"
"foo\nbar\n"
>>> zip [] undefined
[]
>>> unwords ["Lorem", "ipsum", "dolor"]
"Lorem ipsum dolor"
>>> zip undefined []
*** Exception: Prelude.undefined
>>> words (unwords [" "])
[]
>>> unzip [(1, 'a'), (2, 'b')]
([1,2],"ab")
>>> unwords (words "foo\nbar")
"foo bar"
 module Data.Bifunctor where 
 base  bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
https://hackage.haskell.org/package/base-4.18.0.0/ (https://hackage.haskell.org/package/base- bimap f g = first f . second g
4.18.0.0/)
first :: (a -> b) -> p a c -> p b c
 module Control.Applicative where  first f = bimap f id

second :: (b -> c) -> p a b -> p a c


(<*>) :: f (a -> b) -> f a -> f b
second = bimap id
(<*>) = liftA2 id

liftA :: Applicative f => (a -> b) -> f a -> f b


liftA f a = pure f <*> a
 module Data.Char where 
-- Caution: since this may be used for `fmap`, we can't use the obvious
definition of liftA = fmap. isLower :: Char -> Bool

liftA2 :: (a -> b -> c) -> f a -> f b -> f c isUpper :: Char -> Bool
liftA2 f x = (<*>) (fmap f x)
isAlpha :: Char -> Bool
liftA3 :: Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
liftA3 f a b c = liftA2 f a b <*> c isAlpha :: Char -> Bool

isDigit :: Char -> Bool


isDigit c = (fromIntegral (ord c - ord '0') :: Word) <= 9
 module Control.Monad where 
isHexDigit :: Char -> Bool
guard :: (Alternative f) => Bool -> f () isHexDigit c = isDigit c ||
guard True = pure ()
(fromIntegral (ord c - ord 'A')::Word) <= 5 ||
guard False = empty (fromIntegral (ord c - ord 'a')::Word) <= 5
when:: (Applicative f) => Bool -> f () -> f ()
isAscii :: Char -> Bool
when p s = if p then s else pure ()
isAscii c = c < '\x80'
unless :: (Applicative f) => Bool -> f () -> f ()
toUpper :: Char -> Char
unless p s = if p then pure () else s
toLower :: Char -> Char
liftM :: (Monad m) => (a1 -> r) -> m a1 -> m r
liftM f m1 = do { x1 <- m1; return (f x1) }

liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r


liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }

liftM3 :: (Monad m) => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
liftM3 f m1 m2 m3 = do { x1 <- m1; x2 <- m2; x3 <- m3; return (f x1 x2 x3) }

ap :: (Monad m) => m (a -> b) -> m a -> m b


ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
-- Since many Applicative instances define (<*>) = ap, we cannot define ap =
(<*>)
 module Data.Function where   module Data.List where 
(&) :: a -> (a -> b) -> b (++) :: [a] -> [a] -> [a]
x & f = f x (++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ys
-- >>> let fac n = if n <= 1 then 1 else n * fac (n-1) in fac 5
-- 120 head :: HasCallStack => [a] -> a
-- >>> fix (\rec n -> if n <= 1 then 1 else n * rec (n-1)) 5 head (x:_) = x
-- 120 head [] = error "Prelude.head: empty list"
fix :: (a -> a) -> a
fix f = let x = f x in x last :: HasCallStack => [a] -> a
last [x] = x
-- ((+) `on` f) x y = f x + f y last (_:xs) = last xs
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c last [] = error "Prelude.last: empty list"
(.*.) `on` f = \x y -> f x .*. f y
tail :: HasCallStack => [a] -> [a]
applyWhen :: Bool -> (a -> a) -> a -> a tail (_:xs) = xs
applyWhen True f x = f x tail [] = error "Prelude.tail: empty list"
applyWhen False _ x = x
init :: HasCallStack => [a] -> [a]
init [x] = []
init (x:xs) = x : init xs
init [] = error "Prelude.init: empty list"

uncons :: [a] -> Maybe (a, [a])


uncons [] = Nothing
uncons (x:xs) = Just (x, xs)

singleton :: a -> [a]


singleton x = [x]

length :: [a] -> Int


length = foldl' (\c _ -> c+1) 0

map :: (a -> b) -> [a] -> [b]


map _ [] = []
map f (x:xs) = f x : map f xs

reverse :: [a] -> [a]


reverse = foldl (flip (:)) []

-- intersperse ',' "abcde" = "a,b,c,d,e"


intersperse :: a -> [a] -> [a]
intersperse _ [] = []
intersperse sep (x:xs) = x : prependToAll sep xs
prependToAll :: a -> [a] -> [a]
prependToAll _ [] = []
prependToAll sep (x:xs) = sep : x : prependToAll sep xs

-- intercalate ", " ["Lorem", "ipsum", "dolor"] = "Lorem, ipsum, dolor"


intercalate :: [a] -> [[a]] -> [a]
intercalate xs xss = concat (intersperse xs xss)
transpose :: [[a]] -> [[a]] unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
transpose [] = [] unfoldr f b0 = build (\c n ->
transpose ([] : xss) = transpose xss let go b = case f b of
-- with inlined combine: Just (a, new_b) -> a `c` go new_b
-- transpose ((x : xs) : xss) = (x:hds) : transpose (xs:tls) Nothing -> n
transpose ((x : xs) : xss) = combine x hds xs tls in go b0)
where
(hds, tls) = unzip [(hd, tl) | hd : tl <- xss] take :: Int -> [a] -> [a]
combine y h ys t = (y:h) : transpose (ys:t) take n _ | n <= 0 = []
take _ [] = []
-- alternative transpose implementation if all lists in the argument are of take n (x:xs) = x : take (n-1) xs
the same length
transpose' :: [[a]] -> [[a]] drop :: Int -> [a] -> [a]
transpose' [] = [] drop n xs | n <= 0 = xs
transpose' [xs] = map (\x -> [x]) xs drop _ [] = []
transpose' (xs:xss) = zipWith (:) xs (transpose' xss) drop n (_:xs) = drop (n-1) xs

-- subsequences "abc" = ["","a","b","ab","c","ac","bc","abc"] splitAt :: Int -> [a] -> ([a],[a])


subsequences :: [a] -> [[a]] splitAt n xs = (take n xs, drop n xs)
subsequences xs = [] : nonEmptySubsequences xs
nonEmptySubsequences :: [a] -> [[a]] takeWhile :: (a -> Bool) -> [a] -> [a]
nonEmptySubsequences [] = [] takeWhile _ [] = []
nonEmptySubsequences (x:xs) = [x] : foldr f [] (nonEmptySubsequences xs) takeWhile p (x:xs)
where f ys r = ys : (x : ys) : r | p x = x : takeWhile p xs
| otherwise = []
permutations :: [a] -> [[a]]
dropWhile :: (a -> Bool) -> [a] -> [a]
-- alternative permutations implementation if duplicates are not considered dropWhile _ [] = []
permutations' :: (Eq a) => [a] -> [[a]] dropWhile p xs@(x:xs')
permutations' [] = [[]] | p x = dropWhile p xs'
permutations' l = [a:x | a <- l, x <- (permutations' $ delete a l)] | otherwise = xs

scanl :: (b -> a -> b) -> b -> [a] -> [b] dropWhileEnd :: (a -> Bool) -> [a] -> [a]
scanl = scanlGo dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
where
scanlGo :: (b -> a -> b) -> b -> [a] -> [b] -- span p xs = (takeWhile p xs, dropWhile p xs)
scanlGo f q ls = q : (case ls of span :: (a -> Bool) -> [a] -> ([a],[a])
[] -> [] span _ xs@[] = (xs, xs)
x:xs -> scanlGo f (f q x) xs) span p xs@(x:xs')
| p x = let (ys,zs) = span p xs' in (x:ys,zs)
iterate :: (a -> a) -> a -> [a] | otherwise = ([],xs)
iterate f x = x : iterate f (f x)
-- break (> 3) [1,2,3,4,1,2,3,4] = ([1,2,3],[4,1,2,3,4])
repeat :: a -> [a] break :: (a -> Bool) -> [a] -> ([a],[a])
repeat x = xs where xs = x : xs break p = span (not . p)

replicate :: Int -> a -> [a] stripPrefix :: Eq a => [a] -> [a] -> Maybe [a]
replicate n x = take n (repeat x) stripPrefix [] ys = Just ys
stripPrefix (x:xs) (y:ys)
cycle :: HasCallStack => [a] -> [a] | x == y = stripPrefix xs ys
cycle [] = errorEmptyList "cycle" stripPrefix _ _ = Nothing
cycle xs = xs' where xs' = xs ++ xs'
group :: Eq a => [a] -> [[a]]
group = groupBy (==) zipWith :: (a->b->c) -> [a]->[b]->[c]
groupBy :: (a -> a -> Bool) -> [a] -> [[a]] zipWith f = go
groupBy _ [] = [] where
groupBy eq (x:xs) = (x:ys) : groupBy eq zs go [] _ = []
where (ys,zs) = span (eq x) xs go _ [] = []
go (x:xs) (y:ys) = f x y : go xs ys
-- inits = map reverse . scanl (flip (:)) []
inits :: [a] -> [[a]] zipWith3 :: (a->b->c->d) -> [a]->[b]->[c]->[d]
zipWith3 z = go
tails :: [a] -> [[a]] where
go (a:as) (b:bs) (c:cs) = z a b c : go as bs cs
isPrefixOf :: (Eq a) => [a] -> [a] -> Bool go _ _ _ = []
isPrefixOf [] _ = True
isPrefixOf _ [] = False unzip :: [(a,b)] -> ([a],[b])
isPrefixOf (x:xs) (y:ys) = x == y && isPrefixOf xs ys unzip = foldr (\(a,b) ~(as,bs) -> (a:as,b:bs)) ([],[])

isSuffixOf :: (Eq a) => [a] -> [a] -> Bool lines :: String -> [String]

isInfixOf :: (Eq a) => [a] -> [a] -> Bool words :: String -> [String]
isInfixOf needle haystack = any (isPrefixOf needle) (tails haystack)
unlines :: [String] -> String
-- The elements do not have to occur consecutively (but in order). unlines = concatMap (++ "\n")
isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool
isSubsequenceOf [] _ = True unwords :: [String] -> String
isSubsequenceOf _ [] = False unwords [] = ""
isSubsequenceOf a@(x:a') (y:b) | x == y = isSubsequenceOf a' b unwords ws = foldr1 (\w s -> w ++ ' ':s) ws
| otherwise = isSubsequenceOf a b
nub :: (Eq a) => [a] -> [a]
elem :: Eq a => a -> t a -> Bool nub = nubBy (==)
elem = any . (==) nubBy :: (a -> a -> Bool) -> [a] -> [a]
nubBy eq [] = []
filter :: (a -> Bool) -> [a] -> [a] nubBy eq (x:xs) = x : nubBy eq (filter (\ y -> not (eq x y)) xs)
filter _pred [] = []
filter pred (x:xs) delete :: (Eq a) => a -> [a] -> [a]
| pred x = x : filter pred xs delete = deleteBy (==)
| otherwise = filter pred xs deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]
deleteBy _ _ [] = []
partition :: (a -> Bool) -> [a] -> ([a],[a]) deleteBy eq x (y:ys) = if x `eq` y then ys else y : deleteBy eq x ys
partition p xs = foldr (select p) ([],[]) xs
select :: (a -> Bool) -> a -> ([a], [a]) -> ([a], [a]) (\\) :: (Eq a) => [a] -> [a] -> [a]
select p x ~(ts,fs) | p x = (x:ts,fs) (\\) = foldl (flip delete)
| otherwise = (ts, x:fs)
union :: (Eq a) => [a] -> [a] -> [a]
zip :: [a] -> [b] -> [(a,b)] union = unionBy (==)
zip [] _ = [] unionBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
zip _ [] = [] unionBy eq xs ys = xs ++ foldl (flip (deleteBy eq)) (nubBy eq ys) xs
zip (a:as) (b:bs) = (a,b) : zip as bs

-- zip3 = zipWith3 (,,)


zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]
zip3 (a:as) (b:bs) (c:cs) = (a,b,c) : zip3 as bs cs
zip3 _ _ _ = []
intersect :: (Eq a) => [a] -> [a] -> [a]  module Numeric where 
intersect = intersectBy (==)
intersectBy :: (a -> a -> Bool) -> [a] -> [a] -> [a] -- type ShowsS = String -> String
intersectBy _ [] _ = []
intersectBy _ _ [] = [] -- slightly modified
intersectBy eq xs ys = [x | x <- xs, any (eq x) ys] showIntAtBase :: Integral a => a -> (Int -> Char) -> a -> ShowS
showIntAtBase base toChr n0 r0
sortBy :: (a -> a -> Ordering) -> [a] -> [a] | base <= 1 = error ""
sort = sortBy compare | n0 < 0 = error ""
sortBy cmp = foldr (insertBy cmp) [] | otherwise = showIt (quotRem n0 base) r0
where
insert :: Ord a => a -> [a] -> [a] showIt (n,d) r = case n of
insert e ls = insertBy (compare) e ls 0 -> r'
insertBy :: (a -> a -> Ordering) -> a -> [a] -> [a] _ -> showIt (quotRem n base) r'
insertBy _ x [] = [x] where
insertBy cmp x ys@(y:ys') r' = toChr (fromIntegral d) : r
= case cmp x y of
GT -> y : insertBy cmp x ys' showHex :: Integral a => a -> ShowS
_ -> x : ys showHex = showIntAtBase 16 intToDigit

 module Data.Ord where 


comparing :: (Ord a) => (b -> a) -> b -> b -> Ordering
comparing p x y = compare (p x) (p y)

clamp :: (Ord a) => (a, a) -> a -> a


clamp (low, high) a = min high (max a low)

 module Data.Tuple where 


fst :: (a,b) -> a
fst (x,_) = x

snd :: (a,b) -> b


snd (_,y) = y

curry :: ((a, b) -> c) -> a -> b -> c


curry f x y = f (x, y)

uncurry :: (a -> b -> c) -> ((a, b) -> c)


uncurry f p = f (fst p) (snd p)

swap :: (a,b) -> (b,a)


swap (a,b) = (b,a)
 MissingH 
https://hackage.haskell.org/package/MissingH-1.6.0.0/
(https://hackage.haskell.org/package/MissingH-1.6.0.0/)

 module Data.List.Utils where 


merge :: (Ord a) => [a] -> [a] -> [a]
merge = mergeBy (compare)

mergeBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
mergeBy _ [] ys = ys
mergeBy _ xs [] = xs
mergeBy cmp (allx@(x:xs)) (ally@(y:ys))
| (x `cmp` y) <= EQ = x : mergeBy cmp xs ally
| otherwise = y : mergeBy cmp allx ys

-- Returns true if the given list contains any of the elements in the search
list.
hasAny :: Eq a => [a] -> [a] -> Bool
hasAny [] _ = False
hasAny _ [] = False
hasAny search (x:xs) = if x `elem` search then True else hasAny search xs

import Data.List (isPrefixOf)


-- split "," "foo,bar,,baz," = ["foo", "bar", "", "baz", ""]
split :: Eq a => [a] -> [a] -> [[a]]
split _ [] = []
split delim str =
let (firstline, remainder) = breakList (isPrefixOf delim) str in
firstline : case remainder of
[] -> []
x -> if x == delim
then [] : []
else split delim (drop (length delim) x)

-- Similar to Data.List.break, but performs the test on the entire remaining


list instead of just one element.
breakList :: ([a] -> Bool) -> [a] -> ([a], [a])
breakList func = spanList (not . func)

-- Similar to Data.List.span, but performs the test on the entire remaining


list instead of just one element.
spanList :: ([a] -> Bool) -> [a] -> ([a], [a])
spanList _ [] = ([],[])
spanList func list@(x:xs) = if func list then (x:ys,zs) else ([],list)
where (ys,zs) = spanList func xs

countElem :: Eq a => a -> [a] -> Int


countElem i = length . filter (i==)
λ-Kalkül & Typsysteme
λ-Kalkül & Typsysteme
Prädikatenlogik
Formeln
Äquivalenzen
Auswertung
Church-Kodierungen
Church-Zahlen
Church-Booleans
Church-Paare
Church-Listen
Rekursion
Rekursionsoperator
Typsysteme
Typinferenz
Typinferenz für let-Polymorphismus
Prädikatenlogik Äquivalenzen
Die Namen gebundener Variablen dienen letztlich nur der Dokumentation, entscheidend sind
Formeln die Bindungen. t1 und t2 heißen α-äquivalent (t1 = t2 ), wenn t1 in t2 durch konsistente
α

Variablen: x, y , … Umbenennung der λ-gebundenen Variablen überführt werden kann.


Prädikate: P (x), Q, R(x, y), …
Nach dem Extensionalitätsprinzip sind zwei Funktionen gleich, falls ihr Ergebnis für alle
Arithmetik: φ + ψ, φ ,
< ψ φ = ψ ,… Argumente gleich ist. Die Terme λx. f  x und f heißen η-äquivalent (λx. f  x
η
), falls x
= f
Logische Operatoren: φ ∧ ψ , φ ∨ ψ , ¬φ, φ ,…
⇒ ψ nicht freie Variable von f ist.
Quantoren: ∀x. φ, ∃x. φ, …
Auswertung
(mit Formel-Termen φ, ψ)
Ein λ-Term der Form (λx. t1 ) t2 heißt Redex.

β-Reduktion entspricht der Auswertung der Funktionsanwendung auf einem Redex:


(λx. t1 ) t2 ⇒ t1 [x ↦ t2 ]

t1 [x ↦ t2 ]erhält man aus dem Term t1 , wenn man alle freien Vorkommen von x durch t2
ersetzt (Substitution). Substitution ist keine Textersetzung, sondern arbeitet auf der
Termstruktur, d. h. in der Textrepräsentation müssen ggf. Klammern ergänzt werden.

Ein Term, der nicht weiter reduziert werden kann, heißt in Normalform.

Auswertungsstrategien

Volle β-Reduktion: Jeder Redex kann jederzeit reduziert werden.

Normalreihenfolge: Immer der linkeste, äußerste Redex wird reduziert.

Call-By-Name: Reduziere linkesten äußersten Redex, der nicht von einem λ umgeben ist.
Intuition: Reduziere Argumente erst, wenn benötigt. Standard-Auswertungsstrategie für
Funktionen in Haskell (Lazy Evaluation = Call-By-Name + Sharing).

Call-By-Value: Reduziere linkesten Redex, der nicht von einem λ umgeben ist und dessen
Argument ein Wert ist.
Intuition: Wertte Argumente von dem Funktionsaufruf aus.
Auswertungsstrategie in z. B. Java, C, Scheme, ML, … und bei arithmetischen Ausdrücken in
Haskell.

Standardisierungsatz: Wenn t eine Normalform hat, dann findet


Normalreihenfolgenauswertung diese.

Call-By-Name und Call-By-Value werten nicht immer zur Normalform aus (z. B.
λx. (λy. y) x). Call-By-Name terminiert öfter.
Konfluenz Church-Kodierungen
Church-Rosser-Theorem: Der untypisierte λ-Kalkül ist konfluent, d. h. wenn t ⇒

t1 und
t ⇒ t2 , dann gibt es ein t mit t1 ⇒ t und t2 ⇒ t . Church-Zahlen
∗ ′ ∗ ′ ∗ ′

Korollar: Die Normalform eines λ-Terms ist – sofern sie exisitert – eindeutig. c0 = λs. λz. z

c1 = λs. λz. s z


Bei β-Reduktionen ist es also irrelevant, welchen Redex man zuerst reduziert. Aber
c2 = λs. λz. s (s z)
Komplexität bzw. Terminationsverhalten können unterschiedlich sein.
n
cn = λs. λz. s  z

succ = λn. λs. λz. s (n s z)

pred = λn. fst  (n  next  (pair  c0  c0 ))

plus = λm. λn. λs. λz. m s (n s z)

sub = λm. λn. n  pred  m


η
times = λm. λn. λs. n (m s) = λm. λn. λs. λz. n (m s) z
η
exp = λm. λn. n m = λm. λn. λs. λz. n m s z

isZero = λn. n (λx. cf alse ) ctrue

leq = λm. λn. isZero  (sub  m n)

eq = λm. λn. and  (leq  m n) (leq  n m)

Church-Booleans
if b then x else y wird zu b x y

ctrue = λt. λf . t

cf alse = λt. λf . f

not = λp. p cf alse  ctrue

and = λp. λq. p q p

or = λp. λq. p p q

xor = λp. λq. p (not  q) q

Church-Paare
(a, b) wird zu λf . f  a b

pair = λa. λb. λf . f  a b

fst = λp. p (λa. λb. a)

snd = λp. p (λa. λb. b)

next = λp. pair  (snd  p) (succ  (snd  p))  (n, m) ↦ (m, m + 1)

Church-Listen
nil = λn. λc. n

cons = λx. λxs. λn. λc. c x xs

head = λl. l err ctrue   (e.g. err = cf alse )


tail = λl. l err cf alse

null = λl. l ctrue  (λa. λb. cf alse )

replicate = λn. λx. n (cons  x)  nil


Rekursion Typsysteme
Terme, die nicht zu einer Normalform auswerten, divergieren. Diese modellieren unendliche Für n ∈ N0 heißt ∀α1 . … ∀αn . τ Typschema (Kürzel ϕ ). Es bindet freie Typvariablen
Ausführungen. α1 , … , αn in τ .

ω = (λx. x x) (λx. x x) ⇒ (λx. x x) (λx. x x) ⇒ ⋯ Für Typen τ 1 , … , τ n ist der Typ τ [α1 ↦ τ 1 , … , αn ↦ τ n ] eine Instanziierung vom
(λx. x x) (λy. f  (y y)) ⇒

f (f (f (f (…)))) Typschema ∀α1 . … ∀αn . τ . Schreibweise:
(∀α1 . … ∀αn . τ ) ⪰ τ [α1 ↦ τ 1 , … , αn ↦ τ n ], z. B. ∀α. α → α ⪰ int → int .

Rekursionsoperator
ohne Polymorphismus mit Polymorphismus
Rekursive Definition: g = λn. … g … n … (Rumpf verwendet g)
Funktional: G = λg. λn. … g … n …
β β β
Falls G einen Fixpunkt g ∗ hat, d. h. G g ∗ = g

, so g ∗ = G g

= λn. … g

…n

(vergleiche mit Definition von g)


Die rekursive Definition ist äquivalent zum Fixpunkt des Funktionals.
Y = λf . (λx. f  (x x)) (λx. f  (x x))

Y  f

= (λf . (λx. f  (x x)) (λx. f  (x x))) f

⇒ (λx. f  (x x)) (λx. f  (x x))

⇒ f ((λx. f  (x x)) (λx. f  (x x)))

⇐ f  (Y  f )

β
also f  (Y  f ) = Y  f , d. h. Y f ist Fixpunkt von f

Beispiel Fakultät:

fak = λn. (isZero  n) c1  (times  n (fak  (sub  n c1 )))

G = λ fak. λn. (isZero  n) c1  (times  n (fak  (sub  n c1 )))

fak = Y  G
Typinferenz für  let -Polymorphismus
Typinferenz Typschema ta(τ , Γ) = ∀α1 . ∀α2 . … ∀αn . τ heißt Typabstraktion von τ relativ zu Γ,
wobei αi ∈ FV(τ ) ∖ FV(Γ).
Regel Constraint
1. Sammle Constraints aus linkem Teilbaum in Clet
2. Berechne den mgu σlet von Clet
3. Berechne Γ′ := σlet (Γ), x : ta(σlet (αj ), σlet (Γ))

αi = τ c
4. Benutze Γ in rechtem Teilbaum, sammle Constraints in Cbody

5. Ergebnisconstraints sind Clet



∪ Cbody ∪ {αk = αi } mit
C

let
:= {αn = σlet (αn ) ∣ σlet  definiert f ür αn }

αj = αi

αi kann bei  let -Polymorphismus auch eine


(frische) Instanziierung eines Typschemas sein.
 

αi = αj → αk

αk = αj → αi


C ∪ Cbody ∪ {αk = αi }
let
Logische Programmierung
Logische Programmierung
Begriffe
Prolog Predicates
Comparison Operators
Backtracking
Cuts
Arithmetik
Unifikation und Resolution
Unifikationsalgorithmus nach Robinson (1965)
Begriffe Prolog Predicates
Fakten, z. B.  liebt(fritz, fisch). 
Terme werden als Fakten deklariert, per  . . % list membership
member(X,[X|_]).
Terme
member(X,[_|Xs]) :- member(X,Xs).
Atome:  fritz ,  fisch 
beginnen mit Kleinbuchstaben
% list concatenation
Zahlen:  3 ,  4.5  append([],X,X).
Variablen:  X ,  Y1 ,  _X  append([H|T],X,[H|S]) :- append(T,X,S).
beginnen mit Großbuchstaben oder Unterstrich
Term-Listen:  3,4.5,X,fritz  % naive reverse
rev([],[]).
zusammengesetzt:  liebt(fritz, fisch), liebt(fritz, X) 
rev([X|R],Y) :- rev(R,Y1),append(Y1,[X],Y).
Atom am Anfang eines zusammengesetzten Terms heißt Funktor, z. B.  liebt 

Eine Gruppe von Fakten/Regeln mit gleichem Funktor und gleicher Argumentzahl im Regelkopf % efficient reverse
heißt Prozedur oder Prädikat rev(X,Y) :- rev1(X,[],Y).
rev1([],Y,Y).
Ein Prädikat heißt deterministisch, wenn es stets auf höchstens eine Weise erfüllt werden rev1([X|R],A,Y) :- rev1(R,[X|A],Y).
kann; hat es möglicherweise mehrere Lösungen, so heißt es nichtdeterministisch.
% Quicksort
qsort([],[]).
qsort([X|R],Y) :- split(X,R,R1,R2), qsort(R1,Y1), qsort(R2,Y2), append(Y1,
[X|Y2],Y).
split(X,[],[],[]).
split(X,[H|T],[H|R],Y) :- X>H, split(X,T,R,Y).
split(X,[H|T],R,[H|Y]) :- X=<H, split(X,T,R,Y).

% permutations
permute([],[]).
permute([X|R],P) :- permute(R,P1), append(A,B,P1), append(A,[X|B],P).

% natural numbers
nat(0).
nat(X) :- nat(Y), X is Y+1.

% integer square root


sqrt(X,Y) :- nat(Y), Y2 is Y*Y, Y3 is (Y+1)*(Y+1), Y2 =< X, X < Y3.

% goal cannot be proven (≠ logical not)


not(X) :- call(X), !, fail.
not(X).

% dictionary lookup
lookup(N,[(N,A)|_],A1) :- !, A=A1.
lookup(N,[_|T],A) :- lookup(N,T,A).

% list uniqueness
allDifferent([]) :- !.
allDifferent([H|T]) :- not(member(H,T)), allDifferent(T).
Comparison Operators
Comparison Definition Evaluates Backtracking
 X = Y  succeeds if  X  and  Y  unify (match)
grandparent(X,Y)
 X \= Y  succeeds if  X  and  Y  do not unify; i.e. if  not (X = Y)  ┌─────────────┐
call ───►│ X=fritz Y= ├───► success
succeeds if terms  T1  and  T2  are identical; e.g. names of │ │
 T1 == T2 
variables have to be the same fail ◄───┤ ─►2 │◄─── redo
└─────────────┘
 T1 \== T2  succeeds if terms  T1  and  T2  are not identical

 E1 =:= E2  succeeds if values of expressions  E1  and  E2  are equal ✓
jedes Teilziel, das noch nicht endgültig fehlgeschlagen ist, als Box
 E1 =\= E2  succeeds if values of expressions  E1  and  E2  are not equal ✓ in der Box Substitution, die beim Unifizieren des Teilziels mit Regelkopf entstand
succeeds if numeric value of expression  E1  is < numeric Unterbäume der Box sind Teilziele im Rumpf der verwendeten Regel
 E1 < E2  ✓
value of  E2  Choice-Point ist nächste zu probierende Regel bei Reerfüllungsversucht

succeeds if numeric value of expression  E1  is ≤ numeric Algorithmus


 E1 =< E2  ✓
value of  E2 
1. Anlegen und erstmaliges Betreten der Box durch den call-Eingang beim ersten Aufruf des
succeeds if numeric value of expression  E1  is > numeric Teilziels.
 E1 > E2  ✓
value of  E2 
2. Falls keine passende Regel gefunden wird, wird die Box durch den fail-Ausgang verlassen
succeeds if numeric value of expression  E1  is ≥ numeric und gelöscht.
 E1 >= E2  ✓
value of  E2  3. Für eine passende Regel werden Kind-Boxen für Teilziele im Regelrumpf angelegt. Die Box
wird durch den success-Ausgang verlassen. Dieser verweist auf den call-Eingang der
  T1 @< T2  succeeds if  T1  is alphabetically <  T2  ersten Kindbox.
 T1 @=< T2  succeeds if  T1  is alphabetically ≤  T2  4. Falls keine Kinder existieren (Fakt), verweist success auf den call-Eingang des nächsten
Teilziels.
 T1 @> T2  succeeds if  T1  is alphabetically >  T2 
5. Der fail-Ausgang verweist auf den redo-Eingang des vorherigen Teilziels.
 T1 @>= T2  succeeds if  T1  is alphabetically ≥  T2  6. Wird eine Box durch den redo-Eingang betreten, werden mit Hilfe des Choice Points weitere
anwendbare Regeln gesucht. Falls kein Choice Point existiert, wird die Box durch fail
verlassen.
7. Der fail-Ausgang der obersten/ersten Box erzeugt die Ausgabe no.
8. Der success-Ausgang der rechtest-untersten/letzten Box gibt Substitution aus. Falls der
Benutzer alternative Lösungen anfordert, wird die Box durch redo wieder betreten.

% Generatoren für (un-)gerade Zahlen


even(0).
even(X) :-

odd(Y), X is Y+1, X>0.


odd(1).
odd(X) :- even(Y), X is Y+1, X>1.
Ausführungsbaum zum Zeitpunkt der Ausgabe  X=4  für die Anfrage  even(X) :
Cuts
even2(X)
Syntax:  ! 
┌─────────────┐
─────►│ X=X1 ├───┐
Cuts sind als Teilziel immer erfüllbar, aber Reerfüllungsversuch lässt alle Teilziele links vom
│ │ │
Cut sofort fehlschlagen. Ein Cut löscht beim ersten Aufruf alle Choice Points in allen Boxen für
◄─────┤ │◄┐ │
Teilziele links von der Cut-Box.
└─────────────┘ │ │
│ │ Blauer Cut beeinflusst weder Programmlaufzeit, noch -verhalten
┌───────────────────┘ │
Grüner Cut beeinflusst Programmlaufzeit, aber nicht -verhalten
│ │
│ ┌───────────────────┘
Roter Cut beeinflusst das Programmverhalten
│ │ odd2(Y1) X1 is Y1+1 X1 > 0
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ max(X,Y,X) :- X>Y.
│ └►│ Y1=X2 ├───┐ ┌──►│ X1=4 ├────────►│ ├──────► X=4 max(X,Y,Y) :- X=<Y.
│ │ │ │ │ │ │ │ │
└───┤ │◄┐ │ │ ┌─┤ │◄────────┤ │◄────── ; % grüner Cut
└─────────────┘ │ │ │ │ └─────────────┘ └─────────────┘ % wir wissen, dass max deterministisch ist, weshalb wir einen grünen Cut einfügen
│ │ │ │ % dadurch schnellere Ausführung und weniger Speicherbedarf
┌───────────────────┘ │ │ └───────────────────────────────────────────┐ max(X,Y,X) :- X>Y,!.
│ │ │ │ max(X,Y,Y) :- X=<Y.
│ ┌───────────────────┘ └───────────────────────────────────────────┐ │
│ │ even2(Y2) X2 is Y2+1 X2 > 0 │ │ % roter Cut
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ % verwendet man, um Wächter zu ersetzen
│ └►│ Y2=X3 ├───┐ ┌──►│ X2=3 ├────────►│ ├─┘ │ % ist der erste Wächter erfolgreich, wird der zweite nie angewendet
│ │ │ │ │ │ │ │ │ │ max(X,Y,X) :- X>Y,!.
└───┤ │◄┐ │ │ ┌─┤ │◄────────┤ │◄──┘ max(X,Y,Y).
└─────────────┘ │ │ │ │ └─────────────┘ └─────────────┘ % dadurch ist jedoch z. B. max(3,2,2) erfüllbar (fehlerhaft)
│ │ │ │ % das dritte Argument muss uninstanziiert sein:
┌───────────────────┘ │ │ └───────────────────────────────────────────┐ max(X,Y,Z) :- X>Y,!,Z=X.
│ │ │ │ max(X,Y,Y).
│ ┌───────────────────┘ └───────────────────────────────────────────┐ │
│ │ odd1(Y3) X3 is Y3+1 X3 > 0 │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ Faustregel: Der Cut darf erst kommen, wenn man weiß, dass man in der richtigen Regel ist,
│ └►│ Y3=1 ├────────►│ X3=2 ├────────►│ ├─┘ │ aber muss vor der Instanziierung der Ausgabevariablen stehen.
│ │ │ │ │ │ │ │
└───┤ → odd2 │◄────────┤ │◄────────┤ │◄──┘ Außerdem: Nicht der Aufrufer soll den Determinismus durch einen Cut erzwingen, sondern der
└─────────────┘ └─────────────┘ └─────────────┘ Aufgerufene soll den Determinismus garantieren.
Arithmetik Unifikation und Resolution
 B*(C+3)  ≡  '*'(B, '+'(C,3))  Unifikator: Substitution σ unifiziert Gleichung θ = θ

, falls σθ = σθ

. σ unifiziert C , falls
∀c ∈ C gilt: σ unifiziert c.
Auswertung arithmetischer Ausdrücke explizit per Teilziel  is :  X is B*(C+3) 
σ heißt most general unifier (mgu), falls ∀ Unifikator γ ∃ Substitution δ. γ = δ ∘ σ .
Variablen im rechten Term müssen instanziiert sein ( X is X+1  ist nie erfolgreich).

Arithmetische Ausdrücke unifizieren nicht mit Konstanten. Unifikationsalgorithmus nach Robinson (1965)
unify(∅) = [ ]


⎧ unify(C ) θl == θr



⎪ unify([Y ⇒ θ ] C ′ ) ∘ [Y ⇒ θ ]
⎪ r r θl == Y ∧ Y ∉ FV(θr )


⎪ ′
unify([Y ⇒ θl ] C ) ∘ [Y ⇒ θl ] θr == Y ∧ Y ∉ FV(θl )

unify({θl = θr } ⊎ C ) = ⎨ ′ 1 1 n n 1 1
unify(C ∪ {θ = θr , … , θ = θr }) θl = f (θ , … , θ )
⎪ l l l l


⎪ 1 n
⎪ ∧ θr = f (θr , … , θr )




f ail otherwise

Theorem: unify(C ) terminiert und gibt mgu für C zurück, falls C unifizierbar, ansonsten f ail.
Parallelprogrammierung
Parallelprogrammierung
Fundamentals
Amdahl’s Law
Flynn’s Taxonomy
Message Passing Interface (MPI)
Compilation & Execution
Communicators
Setup
Synchronization
Message Exchange
Communication Modes
Data Distribution
Java
Useful classes in java.base
Lambda Expressions
Functional Interfaces
Method References
Thread Programming
Happens-Before
Advanced
Design By Contract & Java Modeling Language (JML)
Liskov Substitution Principle
Fundamentals Message Passing Interface (MPI)

Amdahl’s Law Compilation & Execution


Gives the theoretical (maximal) speedup of a program executed in parallel on n processors.  mpicc  wrapper compiler:  mpicc INPUTFILES 
Possible speedup is limited by the part of a program that cannot be parallelized. Due to
synchronization and communication overhead, this speedup is run (single program, multiple data):  mpirun -np N PROGRAM ARGUMENTS 
hardly reachable in practice. (the same program is automatically executed in all N processes)

T (1) execution time if processes by one processor 1 1 Communicators


S (n) = = = <
p
T (n) execution time if processes by n processors (1 − p) + 1 − p
n Processes communicate via so-called communicators (a group of processes that can
communicate with each other).  MPI_COMM_WORLD  (collection of all processes) is the default.
where p is the parallelizable percentage of the program.
Within a communicator with N processes each process j is identified by its individual rank
Rj ( 0 ≤ Rj < N ).
Flynn’s Taxonomy
SISD: Single Instruction × Single Data Setup
von Neumann architecture: a single instruction stream operates on a single memory
SIMD: Single Instruction × Multiple Data #include <stdio.h>
One instruction is applied on homogeneous data (e.g. an array) #include <mpi.h> // Import MPI commands
e.g. vector processors of early supercomputers
MIMD: Multiple Instruction × Multiple Data int main(int argc, char** args) {
Different processors operate on different data int size;
e.g. today‘s multi-core processors int myrank;
MISD: Multiple Instruction × Single Data MPI_Init(&argc, &args); // Initialize MPI
Multiple instructions are executed simultaneously on the same data
e.g. in redundant architectures or in pipelines of modern processors (controversal // return value (int) of both functions indicates success
view) MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
Task vs. data parallelism:
// there is no implicit master activity, but process 0 is "root" by
Task parallelism: functional decomposition
convention
Define tasks that can be executed in parallel
if (my_rank == 0) {
Tasks should be as independent as possible // branch depending on the rank (MIMD)
Data parallelism: data decomposition // ...
Partition the data on which the same operation is executed in parallel }
Tasks should be able to work on the partitions as independently as possible
printf("Hello world, I have rank %d out of %d.\n", myrank, size);

MPI_Finalize(); // Clean up afterwards

return 0;
}
Temporal Sorting of Messages: There is no global order on communication events, but
Synchronization messages are non-overtaking, i.e. sorted in time between one sender-receiver pair (this is only
true if a matching “receive” is available). Bottom line: first matching receive is served.
Fairness in receiving (from different senders) is not guaranteed.
 int MPI_Barrier(MPI_Comm comm) 
Communication Modes
Blocks until all processes have called it in order to make sure that all processes have reached Synchronous Send ( MPI_Ssend ): No buffer, synchronization (both sides wait for each
a certain point. other)
Send can be initiated before receive was started
int i; Matching receive must be posted, before operation sends anything (“rendezvous
for (i = 0; i < size; i++) { semantics”, non-local operation) – no buffer used
MPI_Barrier(MPI_COMM_WORLD); Can be used for synchronization instead of a barrier
if (i == myrank) { Safest and most portable option
printf("Hello World, I have rank %d out of %d.\n", myrank, size); Order of send and receive operation is irrelevant
} No hidden internal buffers are used
}
Potentially high synchronization overhead
Operation is non-local: matching receive is required
Message Exchange Buffered Send ( MPI_Bsend ): Explicit buffering, no synchronization (no wait for each
other)
Can complete before receive even starts (local operation)
 int MPI_Send(void* buffer, int count, Explicit user-defined buffer is used, allocation with  MPI_Buffer_attach 
MPI_Datatype datatype, int dest, int tag, MPI_Comm Error, if buffer overflow (especially if no receive follows)
No synchronization overhead, but extra copy
comm)  Ready Send ( MPI_Rsend ): No buffer, no synchronization, matching receive must already
be initiated
Receive must initiate before send starts (user is responsible for writing a correct
 int MPI_Recv(void* buffer, int count, program) – if not, behavior is undefined
MPI_Datatype datatype, int source, int tag, No buffer used, data is transferred directly to the receiver
Lowest sender overhead
MPI_Comm comm, MPI_Status* status)  No synchronization, no waiting for receiver
No extra copy to a buffer
Both functions are blocking and synchronous, i.e. no synchronous sending/receiving Standard Send ( MPI_Send ): May buffer or not, can be synchronous (implementation
necessary.  MPI_Send  blocks until the message buffer can be reused.  MPI_Recv  blocks until dependent)
the message is received in the buffer completely. Sends message with unknown receive state
May buffer: buffer may be on sender, receiver or both sides
 void* buffer : the initial memory address of the sender’s / receiver’s buffer
May be synchronous: gets synchronous if hidden buffer size exceeded
 int count : number of elements to send / receive
Can lead to unexpected timing behavior
 MPI_Datatype datatype : type of buffer’s elements (needs to be specified explicitly)
 int source : rank of the source process; wildcard  MPI_ANY_SOURCE  possible There is only one receive mode; it matches all four sending modes.
 int dest : rank of the destination process
 int tag : “context” of the message, e.g. a conversion ID; in  MPI_Recv  wildcard  MPI_Sendrecv  is blocking, but internally parallel in MPI (like threads with join). Send buffers
and receive buffers must be disjoint.  MPI_Sendrecv_replace  available with one buffer for
 MPI_ANY_TAG  possible
send and receive. Can be seen as “OUTIN” parameter semantics.
 MPI_Comm comm : communicator of the process group, e.g.  MPI_COMM_WORLD 
 MPI_Status* status : contains source and tag (which may be unknown due to
wildcards) in  status.MPI_SOURCE  and  status_MPI_TAG 
 int MPI_Isend(void* buf, int count, MPI_Datatype int *msg, msglen, flag=0;
MPI_Status status;
type, int dest, int tag, MPI_Comm comm, MPI_Request request;
MPI_Request* request)  // ...
MPI_Irecv(msg, msglen, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD,
 int MPI_Irecv(void* buf, int count, MPI_Datatype &request);
// ...
type, int src, int tag, MPI_Comm comm, while (flag==0) {
MPI_Request* request)  MPI_Test(&request, &flag, &status);
// waiting for a message, the receiver can perform other operations here
}
Orthogonal to the communication modes, communication can be blocking or non-blocking:

Blocking communication // ...


Call does not return until operation has been completed
It is clear when it is safe to use received or reuse sent data: Send buffer can be safely
be reused when the call returns
Per default, MPI operations are blocking
Non-locking communication
Call returns immediately, independent of the send state
Can perform other operations while waiting for communication completion
Less deadlock possibility
More error-prone: Manually check when the operation is finished and when the send
buffer can be safely reused (or reuse an additional buffer)

Operations with  I  (immediate) for non-blocking communication.

 request  is a pointer to status information about the operation. It can be used to check the
send and receive operations for completion:

 int MPI_Test(MPI_Request* r, int* flag, MPI_Status* s) 


Non-blocking check
 flag  set to  1  if operation completed ( 0  if not yet)
 int MPI_Wait(MPI_Request* r, MPI_Status* s) 
Blocking check
Before After
Data Distribution Operation (⇨ data, ⇩ (⇨ data, ⇩ Explanation
processes) processes)
The typical usage pattern of distribution (breakup) of input data, parallel calculations and
collection of results can be achieved with collective operations, i.e. operations that all A0     A0     root sends data to all
processes in a group (ultimately) need to invoke. Thus, a collective procedure is synchronizing
processes (including itself);
if all processes in a group must have started this procedure before any process can complete Broadcast       A0    
receivers receive provided
its invocation of this procedure. Collective calls that use the same communicator must be
      A0     data in buffer
executed in the same order by all members of a process group.

A0 A1 A2 A0    
 int MPI_Bcast(void* buffer, int count, all receivers get equal-sized
Scatter       A1    
MPI_Datatype t, int root, MPI_Comm comm)  but content-different data
      A2    

 int MPI_Scatter(void* sendbuf, int sendcount, A0     A0 A1 A2 inverse of scatter; root’s buffer


MPI_Datatype sendtype, void* recvbuf, int Gather A1          
contains collected data sorted
by rank (including its own
recvcount, MPI_Datatype recvtype, int root, A2           data)

MPI_Comm comm)  basically gather + broadcast;


multi-broadcast: each process
A0     A0 B0 C0
 int MPI_Gather(void* sendbuf, int sendcount, in communicator collects and
sends the same data to all
Allgather B0     A0 B0 C0
MPI_Datatype sendtype, void* recvbuf, int other processes; at the end,
C0     A0 B0 C0 the buffer of each process has
recvcount, MPI_Datatype recvtype, int root, the same data (including its
own data) in the same order
MPI_Comm comm) 
A0 A1 A2 A0 B0 C0 sender ps sends to receiver pr
 int MPI_Allgather(void* sendbuf, int sendcount, Alltoall B0 B1 B2 A1 B1 C1
only its r-th element; pr stores
information from sender at
MPI_Datatype sendtype, void* recvbuf, int C0 C1 C2 A2 B2 C2 position s

recvcount, MPI_Datatype recvtype, MPI_Comm comm) 

 int MPI_Alltoall(void *sendbuf, int sendcount,


MPI_Datatype sendtype, void *recvbuf, int
recvcount, MPI_Datatype recvtype, MPI_Comm comm) 
int myrank, numprocs;
 int MPI_Reduce(void* sendbuf, void* recvbuf, int double mytime, maxtime, mintime, avgtime;

count, MPI_Datatype type, MPI_Op op, int root, MPI_Comm_rank(MPI_COMM_WORLD, &myrank);


MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm comm) 
MPI_Barrier(MPI_COMM_WORLD);
Applies an operation to the data in  sendbuf  and stores the result in  recvbuf  of the root
process. mytime = MPI_Wtime(); /* get time just before work section */
/* Do some work */
 count : number of columns in the output buffer mytime = MPI_Wtime() - mytime; /* get time just after work section */
 op : operation
 MPI_LAND ,  MPI_BAND ,  MPI_LOR ,  MPI_BOR , … (logical / bitwise) /* compute max, min, and average timing statistics */
MPI_Reduce(&mytime, &maxtime, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
 MPI_MAX ,  MPI_MIN ,  MPI_SUM ,  MPI_PROD , …
MPI_Reduce(&mytime, &mintime, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);
 MPI_MINLOC ,  MPI_MAXLOC  (“causing” rank of local minimum / maximum) MPI_Reduce(&mytime, &avgtime, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

Before if (myrank == 0) {
After
Operation (⇨ data, ⇩ avgtime /= numprocs;
(⇨ data, ⇩ processes)
processes) printf("Min: %lf Max: %lf Avg: %lf\n", mintime, maxtime, avgtime);
}
A0 ◇ B0 ◇ A1 ◇ B1 ◇ A2 ◇ B2 ◇
A0 A1 A2
C0 C1 C2
Reduce B0 B1 B2
       int MPI_Scatterv(void* sendbuf, int* sendcounts,
C0 C1 C2
      int* displacements, MPI_Datatype sendtype, void*
A0 ◇ B0 ◇ A1 ◇ B1 ◇ A2 ◇ B2 ◇
recvbuf, int recvcount, MPI_Datatype recvtype, int
A0 A1 A2
C0 C1 C2 root, MPI_Comm comm) 
A0 ◇ B0 ◇ A1 ◇ B1 ◇ A2 ◇ B2 ◇
Allreduce B0 B1 B2
C0 C1 C2
 int MPI_Gatherv(void* sendbuf, int sendcount,
C0 C1 C2
A0 ◇ B0 ◇ A1 ◇ B1 ◇ A2 ◇ B2 ◇
C0 C1 C2 MPI_Datatype sendtype, void* recvbuf, int*
recvcounts, int* displacements, MPI_Datatype
A0 A1 A2 A0 ◇ B0 ◇ C0    
recvtype, int root, MPI_Comm comm) 
Reducescatter B0 B1 B2 A1 ◇ B1 ◇ C1    

C0 C1 C2 A2 ◇ B2 ◇ C2     allows varying counts for data sent to each process


 sendcounts : integer array with the number of elements to send to each process
A0 A1 A2  displacements : integer array, entry  i  specifies the displacement relative to  sendbuf 
A0 A1 A2 from which to take the outgoing data to process  i  (gaps allowed but no overlaps)
A0 ◇ B0 A1 ◇ B1 A2 ◇ B2  sendtype : data type of send buffer elements (handle)
Scan B0 B1 B2
A0 ◇ B0 ◇ A1 ◇ B1 ◇ A2 ◇ B2 ◇  recvcount : number of elements in receive buffer (integer)
C0 C1 C2  recvtype : data type of receive buffer elements (handle)
C0 C1 C2
Java  interface java.util.Collection<E> extends
Useful classes in  java.base 
Iterable<E> 

Method Signature Description


 interface java.lang.Iterable<T> 
Ensures that this collection contains the
 boolean add(E e) 
specified element (optional operation).
Method Signature Description
 boolean addAll(Collection<? Adds all of the elements in the specified
Performs the given action for each element of the extends E> c)  collection to this collection (optional operation).
 void forEach(Consumer<?
 Iterable  until all elements have been processed or
super T> action)  Removes all of the elements from this collection
the action throws an exception.  void clear() 
(optional operation).
 Iterator<T> iterator()  Returns an iterator over elements of type  T .
Returns  true  if this collection contains the
 boolean contains(Object o) 
specified element.

 boolean Returns  true  if this collection contains all of


containsAll(Collection<?> c)  the elements in the specified collection.

Returns  true  if this collection contains no


boolean isEmpty()
elements.

Returns a possibly parallel  Stream  with this


 Stream<E> parallelStream() 
collection as its source.

Removes a single instance of the specified


 boolean remove(Object o)  element from this collection, if it is present
(optional operation).

Removes all of this collection’s elements that are


 boolean removeAll(Collection<?>
also contained in the specified collection
c) 
(optional operation).

 boolean removeIf(Predicate<? Removes all of the elements of this collection


super E> filter)  that satisfy the given predicate.

Retains only the elements in this collection that


 boolean retainAll(Collection<?>
are contained in the specified collection
c) 
(optional operation).

Returns the number of elements in this


 int size() 
collection.

Returns a sequential  Stream  with this collection


 Stream<E> stream() 
as its source.
 interface java.util.List<E> extends Collection<E>   final class java.util.Optional<T> 

Method Signature Description Method Signature Description

Inserts the specified element at the specified  static <T> Optional<T> empty()  Returns an empty  Optional  instance.
 void add(int index, E element) 
position in this list (optional operation).
If a value is present, returns the value, otherwise
 T get() 
Inserts all of the elements in the specified throws  NoSuchElementException .
 boolean addAll(int index,
collection into this list at the specified
Collection<? extends E> c)   void ifPresent(Consumer<? super If a value is present, performs the given action
position (optional operation).
T> action)  with the value, otherwise does nothing.
Returns the element at the specified position
 E get(int index)   void ifPresentOrElse(Consumer<? If a value is present, performs the given action
in this list.
super T> action, Runnable with the value, otherwise performs the given
Returns the index of the first occurrence of emptyAction)  empty-based action.
 int indexOf(Object o)  the specified element in this list, or  -1  if this
list does not contain the element. If a value is not present, returns  true , otherwise
 boolean isEmpty() 
 false .
Returns the index of the last occurrence of the
 int lastIndexOf(Object o)  specified element in this list, or  -1  if this list If a value is present, returns  true , otherwise
 boolean isPresent() 
does not contain the element.  false .

 static <E> List<E> of(E... Returns an unmodifiable list containing an If a value is present, returns an  Optional 
elements)  arbitrary number of elements.  <U> Optional<U> map(Function<? describing (as if by  ofNullable(T) ) the result
super T,? extends U> mapper)  of applying the given mapping function to the
 void replaceAll(UnaryOperator<E> Replaces each element of this list with the value, otherwise returns an empty  Optional .
operator)  result of applying the operator to that element.
 static <T> Optional<T> of(T Returns an  Optional  describing the given non-
Replaces the element at the specified position value)  null value.
 E set(int index, E element)  in this list with the specified element (optional
operation). Returns an  Optional  describing the given value,
 static <T> Optional<T>
if non-null, otherwise returns an empty
ofNullable(T value) 
 int size()  Returns the number of elements in this list.  Optional .

 void sort(Comparator<? super E> Sorts this list according to the order induced  Optional<T> or(Supplier<? If a value is present, returns an  Optional 
c)  by the specified  Comparator . extends Optional<? extends T>> describing the value, otherwise returns an
supplier)   Optional  produced by the supplying function.
Returns a view of the portion of this list
 List<E> subList(int fromIndex, int
between the specified  fromIndex , inclusive, If a value is present, returns the value, otherwise
toIndex)   T orElse(T other) 
and  toIndex , exclusive. returns  other .

If a value is present, returns the value, otherwise


 T orElseGet(Supplier<? extends
returns the result produced by the supplying
T> supplier) 
function.

If a value is present, returns the value, otherwise


 T orElseThrow() 
throws  NoSuchElementException .
 @FunctionalInterface interface  @FunctionalInterface interface
java.util.function.Function<T,R>  java.util.function.Predicate<T> 
 T  - the type of the input to the function Method Signature Description
 R  - the type of the result of the function
Returns a composed predicate that represents a
 Predicate<T> and(Predicate<?
Method Signature Description short-circuiting logical AND of this predicate and
super T> other) 
another.
 default <V> Function<T,V> Returns a composed function that first
andThen(Function<? super R,? applies this function to its input, and then Returns a predicate that tests if two arguments are
 static <T> Predicate<T>
extends V> after)  applies the after function to the result. equal according to  Objects.equals(Object,
isEqual(Object targetRef) 
Object) .
 R apply(T t)  Applies this function to the given argument.
Returns a predicate that represents the logical
 <V> Function<V,R> Returns a composed function that first  Predicate<T> negate() 
negation of this predicate.
compose(Function<? super V,? applies the before function to its input, and
extends T> before)  then applies this function to the result.  static <T> Predicate<T>
Returns a predicate that is the negation of the
not(Predicate<? super T>
 static <T> Function<T,T> Returns a function that always returns its supplied predicate.
target) 
identity()  input argument.
Returns a composed predicate that represents a
 Predicate<T> or(Predicate<?
short-circuiting logical OR of this predicate and
super T> other) 
 @FunctionalInterface interface another.

 boolean test(T t)  Evaluates this predicate on the given argument.


java.util.function.Supplier<T> 
Lambda Expressions
Method Signature Description

 T get()  Gets a result. public void add(int i, int j) {


return i + j;
}
 @FunctionalInterface interface
java.util.function.Consumer<T>  (int i, int j) -> i + j

Method Signature Description


// parameter types can usually be inferred
 void accept(T t)  Performs this operation on the given argument. (i, j) -> i + j
 Consumer<T> Returns a composed  Consumer  that performs, in
andThen(Consumer<? super T> sequence, this operation followed by the  after 
after)  operation.
Functional Interfaces Thread Programming
A functional interface is an interface that declares a single method and serves as a target for Thread states
lambda expressions. It allows to define anonymous functions with lambda expressions
instead of anonymous classes, which is useful to reduce code lines, allow sequential / parallel
execution of stream operations, pass behavior into methods and increase efficiency with
sleep or
laziness. not runnable
blocked

thread thread
@FunctionalInterface created starts runnable wake up or
new
interface Predicate { (running/ready) unblocked
boolean check(int value);
}
termination,
abortion,
crash
public int sum(List<Integer> values, Predicate predicate) {
int result = 0;
// Could be expressed even more compact with streams terminated
for (int value : values) {
if (predicate.check(value)) result += value;
}
return result;
}  @FunctionalInterface interface java.lang.Runnable 

Method
sum(values, i -> i > 5); Description
Signature

When an object implementing interface  Runnable  is used to create a


 void
Method References run() 
thread, starting the thread causes the object’s  run  method to be called
in that separately executing thread.
Syntax:  object::method 
Happens-Before
class SimpleCheckers { Java defines the happens-before relationship to avoid memory consistency errors
public static boolean checkGreaterThanFive(Integer value) {
If two statements s1 and s2 have a happens-before relationship, Java guarantees that a
return value > 5;
potential write in s1 is visible to s2
}
} The happens-before relation is transitive, so if s1 happens before s2 and s2 before s3,
there is also a happens-before relation between s1 and s3
Each statement has a happens-before relationship to every statement in the thread that
comes later in the program’s order if they have a data dependency
sum(values, SimpleCheckers::checkGreaterThanFive);
There are several statements that introduce additional happens-before relationship:
 Thread.start : all statements executed before starting the thread (within the
starting thread) have a happens-before relationship to statements in the new thread
 Thread.join : all statements in the terminated thread have a happens-before
relationship to the statements following the join
 synchronized : all statements in a  synchronized  block have a happens-before
relationship to all statements in a subsequent execution of a  synchronized  block
using the same monitor
A happens-before relation does not mean that one statements is actually executed before
another
 volatile  Streams

Streams do not require additional memory. Results of stream operations are calculated on
 volatile  ensures that changes to variables are immediately visible to all threads / demand. Stream operations are executed lazy. Any Java collection can be treated as a stream
processors
by calling the  stream()  method.
 volatile  establishes a happens-before relationship: a write to a  volatile  variable
happens-before every subsequent read to that variable  interface java.util.stream.BaseStream<T,S extends BaseStream<T,S>> 
This means that all writes to (potentially different) variables before writing a  volatile 
variable are visible to all reads of that variables after reading the  volatile  variable, https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/stream/BaseStream
because statements within a thread have a happens-before relationship in their program .html (https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/stream/BaseStream.html)
order
 T  - the type of the stream elements
Values are not locally cached in a CPU cache (every read/write directly back to main
 S  - the type of the stream implementing BaseStream
memory)
Compiler/Processor optimizations are disabled: instruction reordering is not possible for
Method Signature Description
the  volatile  variable
Closes this stream, causing all close handlers for this stream
 void close() 
Advanced pipeline to be called.

 boolean Returns whether this stream, if a terminal operation were to be


Futures isParallel()  executed, would execute in parallel.
A  Future<V>  represents the (future) result of an asynchronous computation (i.e.  Callable ).  Iterator<T>
The computation can either be (not yet) finished or cancelled. Results can only be acquired Returns an iterator for the elements of this stream.
iterator() 
when the computation is finished.
 S parallel()  Returns an equivalent stream that is parallel.
 Executors   S sequential()  Returns an equivalent stream that is sequential.
 newSingleThreadExecutor()  creates an Executor using a single thread  S unordered()  Returns an equivalent stream that is unordered.
 newFixedThreadPool(int)  creates a thread pool with reused threads of fixed size
 newCachedThreadPool()  creates a thread pool with reused threads of dynamic size

ExecutorService executorService = Executors.newCachedThreadPool();


List<Future<Integer>> futures = new ArrayList<Future<Integer>>();

for (int i = 0; i < 10; i++) {


final int currentValue = i;
Callable<Integer> myCallable = () -> {return currentValue;};
// ExecutorService::submit expects a Runnable or Callable (overloaded)
// <T> Future<T> submit(Callable<T> callable)
futures.add(executorService.submit(myCallable));
}

for (Future<Integer> future : futures) {


try {
// blocks until the Thread finished and the Future contains the value
Integer result = future.get();
System.out.println(result);
} catch (ExecutionException ex) {}
}

executorService.shutdown();
Method Signature Description
 interface java.util.stream.Stream<T> extends BaseStream<T, Stream<T>> 
 boolean allMatch(Predicate<? super Returns whether all elements of this stream
https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/stream/Stream.html T> predicate)  match the provided predicate.
(https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/stream/Stream.html)
 boolean anyMatch(Predicate<? super Returns whether any elements of this
T> predicate)  stream match the provided predicate.

 <R> R collect(Supplier<R> supplier,


Performs a mutable reduction operation on
BiConsumer<R,? super T> accumulator,
the elements of this stream.
BiConsumer<R,R> combiner) 

Performs a mutable reduction operation on


 <R,A> R collect(Collector<? super
the elements of this stream using a
T,A,R> collector) 
Collector.

Creates a lazily concatenated stream whose


 static <T> Stream<T>
elements are all the elements of the first
concat(Stream<? extends T> a,
stream followed by all the elements of the
Stream<? extends T> b) 
second stream.

Returns the count of elements in this


 long count() 
stream.

Returns a stream consisting of the distinct


 Stream<T> distinct()  elements (according to
 Object.equals(Object) ) of this stream.

Returns, if this stream is ordered, a stream


 Stream<T> dropWhile(Predicate<? consisting of the remaining elements of this
super T> predicate)  stream after dropping the longest prefix of
elements that match the given predicate.

 static <T> Stream<T> empty()  Returns an empty sequential  Stream .

Returns a stream consisting of the elements


 Stream<T> filter(Predicate<? super
of this stream that match the given
T> predicate) 
predicate.

Returns an  Optional  describing some


 Optional<T> findAny()  element of the stream, or an empty
 Optional  if the stream is empty.

Returns an  Optional  describing the first


 Optional<T> findFirst()  element of this stream, or an empty
 Optional  if the stream is empty.

Returns a stream consisting of the results of


 <R> Stream<R> flatMap(Function<? replacing each element of this stream with
super T,? extends Stream<? extends the contents of a mapped stream produced
R>> mapper)  by applying the provided mapping function
to each element.
Method Signature Description Method Signature Description

Returns an  DoubleStream  consisting of the Returns an  IntStream  consisting of the


 IntStream mapToInt(ToIntFunction<?
 DoubleStream results of replacing each element of this results of applying the given function to the
super T> mapper) 
flatMapToDouble(Function<? super T,? stream with the contents of a mapped elements of this stream.
extends DoubleStream> mapper)  stream produced by applying the provided
mapping function to each element.  LongStream Returns a  LongStream  consisting of the
mapToLong(ToLongFunction<? super T> results of applying the given function to the
Returns an  IntStream  consisting of the mapper)  elements of this stream.
 IntStream flatMapToInt(Function<? results of replacing each element of this
super T,? extends IntStream> stream with the contents of a mapped Returns the maximum element of this
 Optional<T> max(Comparator<? super
mapper)  stream produced by applying the provided stream according to the provided
T> comparator) 
mapping function to each element.  Comparator .

Returns an  LongStream  consisting of the  Optional<T> min(Comparator<? super Returns the minimum element of this stream
 LongStream flatMapToLong(Function<? results of replacing each element of this T> comparator)  according to the provided  Comparator .
super T,? extends LongStream> stream with the contents of a mapped  boolean noneMatch(Predicate<? super Returns whether no elements of this stream
mapper)  stream produced by applying the provided T> predicate)  match the provided predicate.
mapping function to each element.
Returns a sequential  Stream  containing a
 void forEach(Consumer<? super T> Performs an action for each element of this  static <T> Stream<T> of(T t) 
single element.
action)  stream.
 static <T> Stream<T> of(T... Returns a sequential ordered stream whose
Performs an action for each element of this values)  elements are the specified values.
 void forEachOrdered(Consumer<?
stream, in the encounter order of the stream
super T> action) 
if the stream has a defined encounter order. Returns a sequential  Stream  containing a
 static <T> Stream<T> ofNullable(T
single element, if non-null, otherwise returns
Returns an infinite sequential unordered t) 
 static <T> Stream<T> an empty  Stream .
stream where each element is generated by
generate(Supplier<? extends T> s) 
the provided  Supplier . Returns a stream consisting of the elements
of this stream, additionally performing the
Returns a sequential ordered  Stream   Stream<T> peek(Consumer<? super T>
provided action on each element as
 static <T> Stream<T> iterate(T produced by iterative application of the action) 
elements are consumed from the resulting
seed, Predicate<? super T> hasNext, given next function to an initial element, stream.
UnaryOperator<T> next)  conditioned on satisfying the given
 hasNext  predicate. Performs a reduction on the elements of
 Optional<T> this stream, using an associative
Returns an infinite sequential ordered reduce(BinaryOperator<T> accumulation function, and returns an
 Stream  produced by iterative application of accumulator)   Optional  describing the reduced value, if
 static <T> Stream<T> iterate(T
a function f to an initial element seed, any.
seed, UnaryOperator<T> f) 
producing a  Stream  consisting of  seed ,
 f(seed) ,  f(f(seed)) , etc. Performs a reduction on the elements of
 T reduce(T identity, this stream, using the provided identity value
Returns a stream consisting of the elements BinaryOperator<T> accumulator)  and an associative accumulation function,
 Stream<T> limit(long maxSize)  of this stream, truncated to be no longer and returns the reduced value.
than  maxSize  in length.
 <U> U reduce(U identity,
Returns a stream consisting of the results of Performs a reduction on the elements of
 <R> Stream<R> map(Function<? super BiFunction<U,? super T,U>
applying the given function to the elements this stream, using the provided identity,
T,? extends R> mapper)  accumulator, BinaryOperator<U>
of this stream. accumulation and combining functions.
combiner) 
 DoubleStream Returns a  DoubleStream  consisting of the Returns a stream consisting of the
mapToDouble(ToDoubleFunction<? super results of applying the given function to the remaining elements of this stream after
T> mapper)  elements of this stream.  Stream<T> skip(long n) 
discarding the first n elements of the
stream.
Method Signature Description
 interface IntStream extends BaseStream<Integer,IntStream> 
Returns a stream consisting of the elements
 Stream<T> sorted()  of this stream, sorted according to natural https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/stream/IntStream.ht
order. ml (https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/stream/IntStream.html)

Returns a stream consisting of the elements


 Stream<T> sorted(Comparator<? super Method Signature Description
of this stream, sorted according to the
T> comparator) 
provided  Comparator .  DoubleStream Returns a  DoubleStream  consisting of the elements of
asDoubleStream()  this stream, converted to  double .
Returns, if this stream is ordered, a stream
 Stream<T> takeWhile(Predicate<? consisting of the longest prefix of elements Returns a  LongStream  consisting of the elements of
super T> predicate)  taken from this stream that match the given  LongStream asLongStream() 
this stream, converted to  long .
predicate.
Returns an  OptionalDouble  describing the arithmetic
Returns an array containing the elements of  OptionalDouble average()  mean of elements of this stream, or an empty optional
 Object[] toArray() 
this stream. if this stream is empty.
Returns an array containing the elements of Returns a  Stream  consisting of the elements of this
this stream, using the provided generator  Stream<Integer> boxed() 
stream, each boxed to an  Integer .
 <A> A[] toArray(IntFunction<A[]> function to allocate the returned array, as
generator)  well as any additional arrays that might be Returns an  OptionalInt  describing the maximum
required for a partitioned execution or for  OptionalInt max()  element of this stream, or an empty optional if this
resizing. stream is empty.

Accumulates the elements of this stream Returns an  OptionalInt  describing the minimum
 List<T> toList()   OptionalInt min()  element of this stream, or an empty optional if this
into a  List .
stream is empty.

 int sum()  Returns the sum of elements in this stream.

 IntSummaryStatistics Returns an  IntSummaryStatistics  describing various


summaryStatistics()  summary data about the elements of this stream.

Type-constrained signatures use  IntPredicate ,  OptionalInt ,  IntConsumer ,


 IntSupplier ,  IntUnaryOperator ,  IntToDoubleFunction ,  IntFunction<? extends U> ,
 IntBinaryOperator  in place of the more generic variants in  BaseStream . Also,  LongStream 
and  DoubleStream  exist with similar methods.
The  collect  operation Atomic Types

 java.util.concurrent.atomic.AtomicInteger 
R collect(
Supplier<R> supplier, // delivers a new result container Method Signature Description
BiConsumer<R,? super T> accumulator, // incorporates new element in the result
BiConsumer<R,R> combiner // combines two values compatible with the result  int get()  Just return the variable.
)
 int incrementAndGet()  Atomically increments and returns the variable.

Pseudocode behavior:  int decrementAndGet()  Atomically decrements and returns the variable

Checks for the old value and replaces it with the new
 boolean
R result = supplier.get(); one. If successful,  true  is returned. If the
compareAndSet(int
for (T element : this stream)  AtomicInteger  does not contain the  oldValue ,  false 
oldValue, int newValue) 
accumulator.accept(result, element); is returned and nothing is done.
return result;
Fork-Join
 combiner  is only used for parallel streams to combine results calculated in parallel.
Fork-Join is a pattern for effectively computing divide-and-conquer
algorithms in parallel. Problems are solved by splitting them into subtasks, solving them in
Map<Integer, List<Person>> groupedByAge = parallel and finally composing the results.
personsInAuditorium
.stream() General algorithm in pseudocode:
.collect(Collectors.groupingBy(Person::getAge));
Result solve(Problem problem) {
if (problem is small enough) {
Atomicity directly solve problem
} else {
Atomic statements are executed complete or not at all, produce no visible side effects until
split problem into independent parts
their completion and are the smallest unit of code that cannot be interleaved (no race
fork new subtasks to solve each part
conditions due to interleaving) but can still produce synchronization errors due to memory
join all subtasks
consistency errors (missing happens-before relationship).
compose results from subresults
Atomic statements in Java: }
}
Reads and writes of reference variables
Reads and writes of most primitive variables (potentially not for  long  and  double )
Reads and writes of all variables declared  volatile  // ...
ForkJoinPool fjPool = new ForkJoinPool();
MyTask myTask = new MyTask(/* ... */);
fjPool.invoke(myTask);
// ...
 receiveBuilder() 
// ForkJoinPool can execute ForkJoinTask  match(Class<P> type, UnitApply<P> apply) 
// concretizations of ForkJoinTask are
 match(Class<P> type, TypedPredicate<P> predicate, UnitApply<P> apply) 
// * RecursiveAction (no result)
// * RecursiveTask (returns result)  matchAny(UnitApply<Object> apply) 
public class MyTask extends RecursiveTask<Integer> {  Receive build() 
private int[] array;  preStart() 
private static final int THRESHOLD = 20;  postStop() 
 preRestart() ,  postRestart() 
public MyTask(int[] arr) {
this.arr = arr;  ActorRef getSelf() 
}  ActorContext getContext() 
 ActorRef getSender() 
// ForkJoinTasks must override compute()
 Props Props.create(Class<?> actorType, Object... parameters) 
@Override
public Integer compute() {  ActorRef actorOf(Props props) 
// split task if it is bigger than the threshold  tell(Object message, ActorRef sender) 
if (arr.length > THRESHOLD) {  Future<?> Patterns.ask( ActorRef target, Object msg, Timeout timeout) 
return ForkJoinTask.invokeAll(createSubtasks())  T Await.result(Future<T> future, Duration duration) 
.stream().mapToInt(ForkJoinTask::join).sum();  stop(ActorRef actorToStop) 
// join subtasks ^
 PoisonPill.getInstance() 
} else {
return processing(arr);
} public class HelloWorldActor extends AbstractActor {
} @Override
public Receive createReceive() {
private Collection<CustomRecursiveTask> createSubtasks() { return receiveBuilder()
// divide array into smaller parts, e.g., two halves .match(String.class,
} message -> message.equals("printHello"),
message -> System.out.println("Hello World!"))
private Integer processing(int[] arr) { .matchAny(message -> unhandled(message))
// do actually interesting computation, e.g., calculate average of .build();
array }
} }
}

ActorSystem actorSystem = ActorSystem.create("MySystem");


Actors & Akka
ActorRef helloWorldActor =
Basic philosophy: Everything is an actor actorSystem.actorOf(Props.create(HelloWorldActor.class));
helloWorldActor.tell("printHello", ActorRef.noSender());
After receiving a message, an actor can send (a finite numbers of) messages to other actors, actorSystem.terminate();
instantiate (a finite numbers of) new actors and/or designate the behavior when receiving the
next message (which means that the actor can make computations and modify its local state,
which influences what it does when receiving the next message). Actors cannot access and
modify the local state of other actors and they keep the mutable state internal and
communicate only via messages.
Syntax Meaning
Design By Contract & Java Modeling Language (JML)  requires C  precondition
Non-redundancy principle (Meyer, 1997): The body of a routine shall not test for the routine’s  ensures C  postcondition
precondition.
 a ==> b   a  implies  b 
Precondition design:
There are two possibilities to deal with a precondition for a method:  a <==> b   a  iff  b 

 a <=!=> b   !(a <==> b) 


Demanding: Assign the responsibility to the client by adding the condition to the routine’s
precondition. Then the client needs to deal with cases where the pre-condition is not met. result of method call (only in
 \result 
Tolerant: Assign the responsibility to the supplier by adding a conditional instruction and postconditions)
handling of violations to the control flow of the method body
value of  E  before method execution
 \old(E) 
(only in postconditions)

 (\forall Declaration; RangeExpression;


∀ quantifier
BodyExpression) 

 (\exists Declaration; RangeExpression;


∃ quantifier
BodyExpression) 

 \max ,  \min ,  \sum , … special quantifiers

field is allowed to be written by method


 assignable 
(default for all fields)

 assignable \nothing  opposite of default

method without side effects (implies


 pure 
 assignable \nothing )

postcondition in case of thrown


 signals (E e) P 
exception

only exceptions which may be thrown by


 signals_only E1, E2, ... 
method

 invariant E  class invariant

reference type declarations can / cannot


 nullable ,  non_null 
(default) be  null 

on the outermost class, set default to


 nullable_by_default 
 nullable 

following lines are private / protected


 private behavior ,  protected behavior 
behavior

 spec_public   public  only for specification


/*@ ensures size == \old(size) – 1 && \result == \old(top());
@ ensures (\forall int i; 0 <= i && i < size; \old(elements[i]) ==
elements[i]);
@ private behavior
@ requires size > 0;
@*/
/*@ nullable @*/ Object pop() { /* ... */ }

/*@ requires size > 0;


@ assignable \nothing;
@*/
Object top() { /* ... */ }

/*@ requires size < 10;


@ signals (NullPointerException npEx) element == null;
@*/
void push(Object element) { /* ... */ }

class Stack {
//@ invariant size >= 0 && size <= 10;
private Object[] elements = new Object[10];
private /*@ spec_public @*/ int size = 0;
// ...
}

public /*@ pure @*/ int getElementCount() { return size; }

Liskov Substitution Principle


Preconditions must not be more restrictive than those of the overwritten method:
PreconditionSuper ⇒ PreconditionSub
Postconditions must be at least as restrictive as those of the overwritten methods:
PostconditionSub ⇒ PostconditionSuper
The class invariants must be at least as restrictive as those of the superclass:
InvariantsSub ⇒ InvariantsSuper

A special case of this is known from parameter and return types of methods
(Co-/Contravariance).
Compiler
Compiler
Syntaktische Analyse (Parsing)
Grammatiken
Rekursiver Abstieg
Semantische Analyse
Namensanalyse
Java Bytecode
Activation Records (Stackframe)
Deskriptoren
Methodenaufruf
Objekterzeugung und -initialisierung
Array anlegen und Arrayzugriff
Feldzugriff
Codeerzeugung
Umgekehrte Polnische Notation (UPN)
Kontrollfluss
Nach der Umformung möchten wir eine SLL(k) -Grammatik mit möglichst kleinem k
(Effizienz), die eindeutig ist und die Operatorpriorität und -assoziativität umsetzt.
Syntaktische Analyse (Parsing)
Präzedenz
Grammatiken
Für jede Präzedenzstufe (mind.) ein Nichtterminal. Produktionen von niedriger zu hoher
Eine Grammatik G = (Σ, V , P , S ) besteht aus einem endlichen Alphabet Σ (Terminale), Priorität.
einer endlichen Menge V von Variablen mit V ∩ Σ = ∅ (Nichtterminale), einem
Expr → Expr + Term ∣ Term
Startsymbol S ∈ V und einer endlichen Menge P von Produktionsregeln der Form l → r
Term → Term + Factor ∣ Factor
mit l ∈ (V ∪ Σ)+ , r ∈ (V ∪ Σ)∗ .
Factor → ( Expr ) ∣ id

Eine Grammatik heißt kontextfrei, wenn jede Produktion die Form A → α mit A ∈ V hat.
Linksfaktorisierung
L(G) = {ω ∈ Σ

∣ S ⇒

ω} ist die Menge aller in der Grammatik ableitbaren Wörter.
Für ein Nichtterminal A längstes gemeinsames Präfix α (mind.) zweier Alternativen
Bei einer Linksableitung (⇒ L ) bzw. Rechtsableitung (⇒ R ) wird eine Produktion stets auf bestimmen.
das linkeste bzw. rechteste Nichtterminal angewendet.
Wenn nichtrivial (α ≠ ε ), Produktionen A → αβ1 ∣ αβ2 ∣ ⋯ durch A → αA

,
SLL-Grammatiken A

→ β1 ∣ β2 ∣ ⋯ (mit neuem Nichtterminal A′ ) ersetzen.

Für χ ∈ Σ∗ ist der k -Anfang k : χ der Präfix der Länge k von χ### …, wobei # ∈ Σ Eliminierung von Linksrekursion
das Ende der Terminalfolge kennzeichnet und ansonsten nicht in der Grammatik auftritt.
Produktionen A → Aα ∣ β durch A → βA

, A′ → αA

∣ ε (mit neuem Nichtterminal A′ )
Für χ ∈ (Σ ∪ V )
+
sind ersetzen.

Firstk (χ) = {β ∣ ∃τ ∈ Σ

: χ ⇒

τ ∧ β = k : τ} Zu jeder kontextfreien Grammatik existiert äquivalente kontextfreie Grammatik ohne
Linksrekursion.
die k -Anfänge der Strings, die aus χ generiert werden können, und
Assoziativität von Operatoren (Beispiel a + b + c ):
Linksassoziativ: (a + b) + c bei Linksrekursion (E → E  + T )
∗ ∗
Followk (χ) = {β ∣ ∃α, ω ∈ (V ∪ Σ)  mit S ⇒ αχω ∧ β ∈ Firstk (ω)}

Rechtsassoziativ: a + (b + c) bei Rechtsrekursion (E → T  + E )


die k -Anfänge der Strings, die hinter χ generiert werden können.
Determinismus / Eindeutigkeit
Algorithmus zur Bestimmung der Follow-Mengen:
Beispiel Uneindeutigkeit (“dangling else”):
1. Follow(S ) = {#} für Startsymbol S ; Follow(N ) = ∅ für N ≠ S .
S → E ∣ if E  then S ∣ if E  then S  else S
2. Für jede Produktion A → αBβ füge First(β) zu Follow(B) hinzu. E → A ∣ B ∣ C ∣ D

3. Für jede Produktion A → αB füge Follow(A) zu Follow(B) hinzu. Uneindeutig z. B. bei if A then if B then C else D (in der Praxis gehört else
4. Für jede Produktion A → αBβ mit β ⇒

ε füge Follow(A) zu Follow(B) hinzu. i. d. R. zum innersten if).
5. Wiederhole bis sich keine Follow-Menge mehr ändert. Nicht zweimal dasselbe NIchtterminal auf der rechten Seite, um Mehrdeutigkeit zu
vermeiden.
Die Indizmenge von A → α ist mit k Token Lookahead genau Firstk (α Followk (A)).

Eine (kontextfreie) Grammatik ist genau dann eine SLL(k) -Grammatik, wenn für alle Paare
von Produktionen A → α ∣ β mit α ≠ β, gilt:

Firstk (α Followk (A)) ∩ Firstk (β Followk (A)) = ∅

Grammar Engineering
Ohne Abstract Syntax Tree:
Rekursiver Abstieg
void parseTList() {
Genau dann, wenn G eine SLL(k) -Grammatik ist, ist G mit k -Lookahed im rekursiven
switch(lexer.current) {
Abstieg parsebar. case STAR:
expect(TokenType.STAR);
Pro Nichtterminal eine Parse-Funktion, die Lookahead inspiziert und darauf basierend
parseF();
Produktion anhand derer Indizmengen auswählt. Falls k = 1 Produktionsauswahl mit
parseTList();
 switch  über aktuelles Token. break;
case SLASH:
void expect(TokenType e) { expect(TokenType.SLASH);
if (lexer.current == e) { parseF();
lexer.lex(); parseTList();
} else { break;
error(); case PLUS:
} case MINUS:
} case R_PAREN:
case EOF:
break;
Arithmetische Ausdrücke default:
error("Expected one of */+-)# but got ", lexer.current);
T → F TList }
TList → * F TList ∣ / F TList ∣ ε }
F → id ∣ ( E )
void parseT() {
parseF();
paresTList();
}

Mit Abstract Syntax Tree:

abstract class Expr { /* ... */ };

class Mult extends Expr {


Expr left;
Expr right;
Mult(Expr left, Expr right) { /* ... */ }
}

class Div extends Expr { /* ... */ }

class Val extends Expr {


int i;
Val(int i) { /* ... */ }
}

class Var extends Expr { /* ... */ }


Mit Abstract Syntax Tree und Endrekursion in Schleife transformiert:
Expr parseTList(Expr left) {
// Linksassoziativtät (linke AST-Knoten müssen mitgereicht werden)
Expr res = left; Expr parseTList(Expr leftmost) {
Expr res = leftmost;
switch(lexer.current) { loop:
case STAR: while (true) {
expect(TokenType.STAR); switch(lexer.current) {
res = new Mult(res, parseF()); case STAR:
return parseTList(res); expect(TokenType.STAR);
case SLASH: res = new Mult(res, parseF());
expect(TokenType.SLASH); return parseTList(res);
res = newDiv(res, parseF()); continue;
return parseTList(res); case SLASH:
case PLUS: expect(TokenType.SLASH);
case MINUS: res = newDiv(res, parseF());
case R_PAREN: return parseTList(res);
case EOF: continue;
break; case PLUS:
default: case MINUS:
error("Expected one of */+-)# but got ", lexer.current); case R_PAREN:
} case EOF:
break loop;
return res; default:
} error("Expected one of */+-)# but got ", lexer.current);
}
Expr parseT() { }
Expr leftmost = parseF();
return paresTList(leftmost); return res;
} }

Expr parseT() {
Expr leftmost = parseF();
return paresTList(leftmost);
}
2. Unmittelbar vor Eintritt in Bereich 1
Namenskeller:
Semantische Analyse
Bereich Liste … …

Namensanalyse  foo   bar 


0
vorherige Definition: — vorherige Definition: —
Vorgehen: Durchlaufe AST und sammle Informationen in Symboltabelle
Stringtabelle:
Die Symboltabelle enthält Informationen zur (momentanen) Definition von Bezeichnern,
Index Bezeichner Definition
unterstützt Verschachtelung von Namensbereichen und (optional) getrennte Namensräume.
0  foo  Zeile 2
Ziel sind Abfragen in O(1) durch Vermeiden von Suche mithilfe einer Stringtabelle.
Implementiert wird eine zentrale Datenstruktur außerhalb des Syntaxbaums, sodass der 1  bar  Zeile 3
Aufbau unabhängig von Besuchssequenzen ist und bei Eintritt/Verlassen eines
Namensraums sich der gültige Teil der Tabelle ändert. Hierzu wird ein Stack von 3. Ende von Bereich 1
Namensbereichen angelegt, wobei jeder Bereich eine Liste von Definitionen enthält. Bei der Namenskeller:
Definition eines Bezeichners merke vorherige Definition in Liste, beim Verlassen eines
Bereich Liste … …
Namensbereichs stelle vorherige Definitionen anhand der Liste wieder her. Nach dem
Analyseende ist der Namenskeller wieder leer, er wird nur während der Analyse verwendet.  foo 
1
vorherige Definition: Zeile 2
AST-Traversierung: Single-Pass-Compilation (einfacher AST-Durchlauf mit Namensanalyse
während des Parsens) bei einfachem Typsystem und “Definition vor Verwendung” möglich.  foo   bar 
0
Bei Verwendung vor Definition sollten vor Betreten eines Unterbereichs alle Namen in die vorherige Definition: — vorherige Definition: —
Symboltabelle eingetragen werden (kein Single-Pass mehr möglich). Umsetzung mit dem
Visitor-Pattern. Stringtabelle:
Index Bezeichner Definition
1 /* Bereich 0 */
2 int foo; 0  foo  Zeile 5
3 int bar; 1  bar  Zeile 3
4 { /* Bereich 1 */
5 int foo;
4. Unmittelbar nach Bereich 1
6 }
Namenskeller:
Bereich Liste … …
1. Beginn von Bereich 0
Namenskeller:  foo   bar 
0
vorherige Definition: — vorherige Definition: —
Bereich Liste

0 Stringtabelle:
Index Bezeichner Definition
Stringtabelle:
0  foo  Zeile 2
Index Bezeichner Definition
1  bar  Zeile 3
0  foo  —

1  bar  —
Stack Stack
Mnemonic Description Forms
Java Bytecode (before) (after)

 d2f ,  d2i ,
https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-6.html
 d2l ,  f2d ,
(https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-6.html)
 f2i ,  f2l ,
 i2b ,  i2c ,
Prefix ( ? ) Type  ?2?  …, value …, result Convert  int  to  byte .
 i2d ,  i2f ,
 a  Reference  i2l ,  i2s ,
 l2d ,  l2f ,
 b   byte / boolean  (often represented using  int )  l2i 
 c   char  Push the  null  object
 aconst_null  … …, null reference onto the
 s   short 
operand stack.
 i   int 
The values are popped
 l   long  from the operand
stack. The  ?  result is
 f   float  …, value1,  dadd ,  fadd ,
 ?add  …, result  value1 + value2 .
value2  iadd ,  ladd 
The result is pushed
 d   double 
onto the operand
stack.

 aaload ,
 baload ,
 caload ,
…, arrayref,  daload ,
 ?aload  …, value Load  ?  from array.
index  faload ,
 iaload ,
 laload ,
 saload 

An  ?  result is
calculated by taking
the bitwise AND
…, value1,
 ?and  …, result (conjunction) of value1  iand ,  land 
value2
and value2. The result
is pushed onto the
operand stack.
Stack Stack Stack Stack
Mnemonic Description Forms Mnemonic Description Forms
(before) (after) (before) (after)

Create new array of The values are popped


reference. The from the operand
unsigned  indexbyte1  stack. The  ?  result is
and  indexbyte2  are the value of the Java
…, value1,  ddiv ,  fdiv ,
used to construct an  ?div  …, result programming language
value2  idiv ,  ldiv 
index into the run-time expression  value1 /
constant pool of the value2 . The result is
current class. The pushed onto the
named class, array, or operand stack.
interface type is
resolved. A new array Duplicate the top value
 anewarray with components of on the operand stack
…, …, value,
<indexbyte1> …, count that type, of length  dup  …, value and push the
arrayref value
<indexbyte2>  count, is allocated duplicated value onto
from the garbage- the operand stack.
collected heap, and a The run-time constant
reference arrayref to pool entry at the index
this new array object is must be a symbolic
pushed onto the reference to a field,
operand stack. All which gives the name
components of the and descriptor of the
new array are field as well as a
initialized to  null , the symbolic reference to
default value for the class in which the
reference types. field is to be found.
 getfield
 arraylength  …, arrayref …, length Get length of array. …, The referenced field is
<indexbyte1> …, value
objectref resolved. The
<indexbyte2> 
 aastore , objectref, which must
 bastore , be of type reference
 castore , but not an array type,
…, arrayref,
 dastore , is popped from the
 ?astore  index, … Store into  ?  array.
 fastore , operand stack. The
value
 iastore , value of the referenced
 lastore , field in objectref is
 sastore  fetched and pushed
onto the operand
…, Throw exception or stack.
 athrow  objectref
objectref error.

The immediate  byte 


is sign-extended to an
 bipush
… …, value  int  value. That value
<byte> 
is pushed onto the
operand stack.
Stack Stack Stack Stack
Mnemonic Description Forms Mnemonic Description Forms
(before) (after) (before) (after)

The run-time constant  iconst_m1 ,


pool entry at the index  iconst_0 ,
must be a symbolic Push the  ?  constant  iconst_1 ,
reference to a field,  <n>  onto the operand  iconst_2 ,
which gives the name stack. Each of the  iconst_3 ,
and descriptor of the  int  family of  iconst_4 ,
field as well as a instructions is  iconst_5 ,
 ?const_<n>  … …,  <n> 
symbolic reference to equivalent to  bipush  lconst_0 ,
the class or interface <n>  for the respective  lconst_1 ,
in which the field is to value of  <n> , except  fconst_0 ,
be found. The that the operand  <n>   fconst_1 ,
 getstatic referenced field is is implicit.  fconst_2 ,
<indexbyte1> …, …, value resolved. On  dconst_0 ,
<indexbyte2>  successful resolution  dconst_1 
of the field, the class
or interface that  ifnonnull
Branch if reference not
declared the resolved <branchbyte1> …, value …
 null .
field is initialized if <branchbyte2> 
that class or interface  ifnull
has not already been Branch if reference is
<branchbyte1> …, value …
initialized. The value of  null .
<branchbyte2> 
the class or interface
field is fetched and Increment local
pushed onto the variable by constant.
operand stack. The  const  is an
immediate signed
Execution proceeds at byte. The local variable
that offset from the at  index  must
address of the opcode  iinc <index>
… … contain an  int . The
of this goto <const> 
 goto value  const  is first
instruction. The target sign-extended to an
<branchbyte1> … …
address must be that  int , and then the
<branchbyte2> 
of an opcode of an local variable at
instruction within the  index  is incremented
method that contains by that amount.
this goto instruction.

 if<cond> Branch if  int   ifeq ,  ifne ,


<branchbyte1> …, value … comparison with zero  iflt ,  ifge ,
<branchbyte2>  succeeds.  ifgt ,  ifle 

 if_acmpeq ,
 if_acmpne ,
 if_?  if_icmpeq ,
comp<cond> …, value1, Branch if  ?   if_icmpne ,

<branchbyte1> value2 comparison succeeds.  if_icmplt ,
<branchbyte2>   if_icmpge ,
 if_icmpgt ,
 if_icmple 
Stack Stack Stack Stack
Mnemonic Description Forms Mnemonic Description Forms
(before) (after) (before) (after)

The run-time constant The run-time constant


pool entry at the index pool entry at the index
must be a symbolic must be a symbolic
reference to a method reference to a method,
or an interface method, which gives the name
which gives the name and descriptor of the
and descriptor of the method as well as a
method or interface symbolic reference to
method as well as a the class in which the
symbolic reference to method is to be found.
the class or interface The named method is
in which the method or resolved. If the
interface method is to resolved method is not
be found. The named signature polymorphic,
method is resolved. then the
The resolved method  invokevirtual 
…,
must not be an  invokevirtual instruction proceeds
objectref,
instance initialization <indexbyte1> … as follows. Let C be
[arg1, [arg2
method, or the class or <indexbyte2>  the class of objectref.
…]]
 invokestatic interface initialization A method is selected
…, [arg1,
<indexbyte1> … method. The resolved with respect to C and
[arg2 …]]
<indexbyte2>  method must be the resolved method.
 static , and therefore This is the method to
cannot be  abstract . be invoked. The
On successful objectref must be
resolution of the followed on the
method, the class or operand stack by
interface that declared nargs argument values,
the resolved method is where the number,
initialized if that class type, and order of the
or interface has not values must be
already been consistent with the
initialized. The operand descriptor of the
stack must contain selected instance
nargs argument values, method.
where the number,
type, and order of the  aload ,
The  ?  in the local
values must be  dload ,
 ?load variable at  index  is
consistent with the … …, value  fload ,
<index>  pushed onto the
descriptor of the  iload ,
operand stack.
resolved method.  lload 

 aload_<n> ,
The  ?  in the local
 dload_<n> ,
 ?load_<n>  variable at  n  is
… …, value  fload_<n> ,
(0 ≤  n  ≤ 3) pushed onto the
 iload_<n> ,
operand stack.
 lload_<n> 
Stack Stack Stack Stack
Mnemonic Description Forms Mnemonic Description Forms
(before) (after) (before) (after)

The values are popped The count must be of


from the operand type  int . It is popped
stack. The  ?  result is off the operand stack.
…, value1,  dmul ,  fmul ,
 ?mul  …, result  value1 * value2 . The count represents
value2  imul ,  lmul 
The result is pushed the number of
onto the operand elements in the array
stack. to be created. The
 atype  is a code that
The int result is the indicates the type of
arithmetic negation of array to create. It must
 dneg ,  fneg ,
 ?neg  …, value …, result  value ,  -value . The take one of the
 ineg ,  lneg 
result is pushed onto following values:  4 
the operand stack. ( boolean ),  5 
The run-time constant ( char ),  6  ( float ),
pool entry at the index  7  ( double ),  8 
must be a symbolic ( byte ),  9  ( short ),
 newarray …,
reference to a class or …, count  10  ( int ),  11 
<atype>  arrayref
interface type. The ( long ). A new array
named class or whose components
interface type is are of type  atype  and
resolved and should of length count is
result in a class type. allocated from the
Memory for a new garbage-collected
 new heap. A reference
…, instance of that class
<indexbyte1> … arrayref to this new
objectref is allocated from the
<indexbyte2>  array object is pushed
garbage-collected
heap, and the instance into the operand stack.
variables of the new Each of the elements
object are initialized to of the new array is
their default initial initialized to the
values. The objectref, a default initial value for
reference to the the element type of the
instance, is pushed array type.
onto the operand  nop  … … Do nothing.
stack.
An  ?  result is
calculated by taking
the bitwise inclusive
…, value1,
 ?or  …, result OR of value1 and  ior ,  lor 
value2
value2. The result is
pushed onto the
operand stack.

Pop the top value from


 pop  …, value …
the operand stack.
Stack Stack Stack Stack
Mnemonic Description Forms Mnemonic Description Forms
(before) (after) (before) (after)

The run-time constant The run-time constant


pool entry at the index pool entry at the index
must be a symbolic must be a symbolic
reference to a field, reference to a field,
which gives the name which gives the name
and descriptor of the and descriptor of the
field as well as a field as well as a
symbolic reference to symbolic reference to
the class in which the the class or interface
field is to be found. in which the field is to
The referenced field is be found. The
resolved. The type of a referenced field is
value stored by a resolved. On
 putfield  instruction successful resolution
must be compatible of the field, the class
with the descriptor of or interface that
the referenced field. If declared the resolved
the field descriptor field is initialized if
 putfield …,
type is  boolean , that class or interface
<indexbyte1> objectref, …
 byte ,  char ,  short , has not already been
<indexbyte2>  value
or  int , then the value  putstatic initialized. The type of
must be an  int . If the <indexbyte1> …, value … a value stored by a
field descriptor type is <indexbyte2>   putstatic  instruction
 float ,  long , or must be compatible
 double , then the with the descriptor of
value must be a the referenced field. If
 float ,  long , or the field descriptor
 double , respectively. type is  boolean ,
The value and  byte ,  char ,  short ,
objectref are popped or  int , then the value
from the operand must be an  int . If the
stack. The objectref field descriptor type is
must be of type  float ,  long , or
reference but not an  double , then the
array type. The value must be a
referenced field in  float ,  long , or
objectref is set to  double , respectively.
value. The value is popped
from the operand
stack. The referenced
field in the class or
interface is set to
value.
Stack Stack Stack Stack
Mnemonic Description Forms Mnemonic Description Forms
(before) (after) (before) (after)

The values are popped The values are popped


from the operand from the operand
stack. The int result is stack. An  ?  result is
…, value1,  value1 - (value1 /  drem ,  frem , calculated by shifting
 ?rem  …, result
value2 value2) * value2 .  irem ,  lrem  value1 right by s bit
…, value1,
The result is pushed  ?shr  …, result positions, with sign  ishr ,  lshr 
value2
onto the operand extension, where s is
stack. the value of the low 5
bits of value2. The
The local variable at result is pushed onto
 index  in the current the operand stack.
frame must contain a
value of type  astore ,
returnAddress. The The value of the local  dstore ,
 ?store
 ret <index>  … … contents of the local …, value … variable at index is set  fstore ,
<index> 
variable are written to  value .  istore ,
into the Java Virtual  lstore 
Machine’s pc register,
and execution  astore_<n> ,
continues there. The value of the local  dstore_<n> ,
 ?store_<n> 
…, value … variable at  n  is set to  fstore_<n> ,
(0 ≤  n  ≤ 3)
The current method  value .  istore_<n> ,
must have return type  lstore_<n> 
void. The interpreter
 return  … empty then returns control to The values are popped
the invoker of the from the operand
method, reinstating the stack. The  ?  result is
frame of the invoker.  value1 - value2 .
…, value1, The result is pushed  dsub ,  fsub ,
 ?sub  …, result
 areturn , value2 onto the operand  isub ,  lsub 
 dreturn , stack. For  int 
Return  ?  from
 ?return  …, value empty  freturn , subtraction,  a-b 
method.
 ireturn , produces the same
 lreturn  result as  a+(-b) .

The values are popped The values are popped


from the operand from the operand
stack. An  ?  result is stack. An  ?  result is
calculated by shifting calculated by shifting
…, value1, value1 left by s bit value1 right by s bit
 ?shl  …, result  ishl ,  lshl  …, value1,  iushr ,
value2 positions, where s is  ?ushr  …, result positions, with zero
value2  lushr 
the value of the low 5 extension, where s is
bits of value2. The the value of the low 5
result is pushed onto bits of value2. The
the operand stack. result is pushed onto
the operand stack.
Stack Stack
Mnemonic Description Forms Deskriptoren
(before) (after)

An  ?  Namen von Typen, Feldern und Methoden müssen einem festgelegtem
result is Schema entsprechen.
calculated
by taking Art Schema
the bitwise
exclusive Objekttypen:  java.lang.Object   Ljava/lang/Object; 
OR of  ixor ,
 ?xor  Primitive Typen:  int ,  void ,  boolean , …  I ,  V ,  Z , …
value1 and  lxor 
value2.  foo(ILjava/lang/Object;)V 
The result Methoden:  void foo(int, Object) 
(identifiziert über Name × Deskriptor)
is pushed
onto the  b:Z 
Felder:  boolean b 
operand (identifiziert über Name)
stack.
Konstruktoren Name:  <init> , Static Initializer: <clinit> 

Activation Records (Stackframe) Methodenaufruf


1.  this -Parameter  p0  auf den Operandenstack (falls nicht  static )
Activation Records enthalten die lokalen Variablen einer Methode. Bei Rekursion hat jede 2. Parameter  p1 , …,  pn  auf den Operandenstack
Inkarnation eigenen Satz lokaler Variablen (bei jedem Methodenaufruf neuen AR anlegen). Er
3.  invokevirtual  /  invokestatic  ausführen; automatisch passiert:
wird bei Rückkehr wieder entfernt (dynamisch pulsierender AR Stack).
1. neuen Activation Record anlegen
Aufbau: 2. Rücksprungadresse (Program Counter + 1) und dynamischen Vorgänger
(Framepointer) in Activation Record sichern
Rücksprungadresse 3. Neuen Framepointer setzen
dynamischer Vorgänger 4. Parameter ( p1 , …,  pn , ggf.  p0 ) vom Operandenstack in neuen Activation Record
lokale Variablen kopieren
Methodenparameter (Impliziter  this -Parameter an Position  0 ):  p0 ,  p1 , … 5. zu Methodenanfang springen
Lokale Variablen:  v0 ,  v1 , … 4. Code wird ausgeführt
Operandenstack 5. Rückgabewert auf den Operandenstack
Activation-Records liegen i. A. auf dem Laufzeit-Stack. Framepointer zeigt auf aktuellen 6.  ?return  ( ireturn ,  areturn , …) ausführen; automatisch passiert:
Activation-Record. 1. alten Framepointer setzen und zur Rücksprungadresse springen
2. Rückgabewert aus Operandenstack des neuen Activation Records in alten
Operandenstack kopieren
public class Test {
Objekterzeugung und -initialisierung
int bar() {
return foo(42); 1. Objekt anlegen (Speicher reservieren)
} 2. Objekt initialisieren (Konstruktor aufrufen)

int foo(int i) {
return i; class Test {
} // jede Klasse braucht einen Konstruktor (sonst Defaultkonstruktor)
} Test foo() {
return new Test();
}
}
int bar();
aload_0
bipush 42
invokevirtual #2 // s. Konstantenpool Test();
ireturn aload_0
invokespecial #1;
int foo(int); return
iload_1
ireturn Test foo();
new #2;
dup
Konstantenpool: invokespecial #3;
areturn
#2 = Method #3.#16
#3 = class #17 Konstantenpool:
#11 = Asciz foo
#12 = Asciz (I)I
#16 = NameAndType #11:#12 #1 java/lang/Object.<init>()V
#17 = Asciz Test #2 Test
#3 Test.<init>()V
Array anlegen und Arrayzugriff Codeerzeugung
int[] array = new int[10];
array[7] = 42; Umgekehrte Polnische Notation (UPN)
Natürliche Darstellung für Stackmaschinen (entspricht der Befehlsreihenfolge von Java
Bytecode). Eindeutig, auch ohne Präzedenzen und Klammern.
bipush 10 // Konstante 10
newarray int // Array anlegen vom Typ int
astore 1 // in Variable array (var 1) speichern Ausdruck Ausdruck in UPN
aload 1 // Variable array (var 1) laden  7 * 4   7 4 * 
bipush 7 // Konstante 7
bipush 42 // Konstante 42  2 * (2 + 3)   2 2 3 + * 
iastore // Wert (42) in Array−Index (7) von Array ("array") schreiben
return // Aus Funktion zurueckkehren  5 + y + 3 * 5   5 y + 3 5 * + 

Postfixordnung (Befehlserzeugung beim Verlassen eines Knotens, also nachdem Kinder


Feldzugriff besucht sind) bei Tiefensuche in AST erzeugt UPN.

Erzeugter Bytecode für  (x + 3) * (y - 2) :


class Foo {
public Bar field;
iload 42 // x
public void setNull() { iconst_3
field = null; iadd
} iload 17 // y
} iconst_2
isub
imul
aload 0 // Parameter 0 (this) auf Stack
aconst null // null−Referenz auf den Stack
putfield Foo.field:LBar; // Schreibe Wert (null)
// in Feld Foo.field von Objekt (this)
return // Aus Funktion zurueckkehren
Codegen für Ausdrücke if

class Number extends Expr { if (x == 4) {


public void codeGen() { A
// bipush akzeptiert Werte zwischen -128 und 127 } else {
// größere Werte müssen in Konstantenpool gelegt werden B
writer.printf(" bipush %d", this.asInt()); }
}
}
iload 0 // x
class BinOp extends Expr { bipush 4
public void codeGen() {
if_icmpeq label0 // falls gleich, springe zu label0
this.left.codeGen();
goto label1
this.right.codeGen(); label0:
switch (this.opType) {
A // then−Teil
case ADD: writer.printf(" iadd"); break;
goto label2
case SUB: writer.printf(" isub"); break; label1:
case MUL: writer.printf(" imul"); break; B // else−Teil
case DIV: writer.printf(" idiv"); break;
goto label2
}
label2:
} // weitere Befehle
public void codeGen(String trueLabel, String falseLabel) {
// s. Codegen für if Codegen für if
}
}
class If extends Statement {
class Var extends Expr { public void codeGen() {
public void codeGen() { // Hilfsmethode makeLabel() erzeugt neue eindeutige Sprungmarke
// Suche in aktueller Symboltabelle (oberster Eintrag des ST−Stacks) String thenLabel = makeLabel();
STentry se = currentSymTab.search(this); String elseLabel = makeLabel();
writer.printf(" iload %d", se.offset);
} // generiert auch dazugehörige Sprünge
} this.condition.codeGen(thenLabel, elseLabel);

writer.printf("%s:", thenLabel);
Kontrollfluss this.thenStatement.codeGen()
Jeder AST-Knoten ruft rekursiv  codeGen() -Methode seiner Kinder auf.
String afterLabel = makeLabel();
Jede Kontrollstruktur generiert ihren Code so, dass sie nur “per fall-through” verlassen writer.printf(" goto %s", afterLabel);
wird.
Hintereinander ausgeführte  codeGen() -Methoden generieren nacheinander writer.printf("%s:", elseLabel);
ausgeführten Code! if (this.elseStatement != null)
Codeerzeugung für Bedingungen (z. B.  <= ) bekommt zwei Sprungziele übergeben, zu this.elseStatement.codeGen();
denen dann der erzeugte Code je nach Laufzeitwert der Bedingung springt.
writer.printf("%s:", afterLabel);
}
Ergänzung zu Codegen für Ausdrücke:
Kurzauswertung

class BinOp extends Expr { 1. Erzeuge Label  l , das angesprungen wird, falls rechte Seite ausgewertet werden muss.
public void codeGen() { /* ... */ } // Arithmetische Ausdrücke, s. o.
2. Code für rechte Seite hinter  l  platzieren.
public void codeGen(String trueLabel, String falseLabel) {
String cmpsuffix = null; void genShortCircuitAnd(String definitelyTrue, String definitelyFalse) {
switch (this.opType) { // label to jump to if right side must also be evaluated
case LOGICALAND: genShortCircuitAnd(trueLabel, falseLabel); String unsureYet = makeLabel();
return;
case LOGICALOR: genShortCircuitOr(trueLabel, falseLabel); this.left.codeGen(unsureYet, definitelyFalse);
return;
case EQUAL: cmpsuffix = "eq"; break; writer.printf("%s:", unsureYet);
case NOTEQUAL: cmpsuffix = "ne"; break; this.right.codeGen(definitelyTrue, definitelyFalse);
case LESS: cmpsuffix = "lt"; break; }
case LESSEQUAL: cmpsuffix = "le"; break;
case GREATER: cmpsuffix = "gt"; break; void genShortCircuitOr(String definitelyTrue, String definitelyFalse) {
case GREATEREQUAL: cmpsuffix = "ge"; break; // label to jump to if right side must also be evaluated
} String unsureYet = makeLabel();

this.left.codeGen(); this.left.codeGen(definitelyTrue, unsureYet);


this.right.codeGen();
writer.printf(" if_icmp%s %s", cmpsuffix, trueLabel); writer.printf("%s:", unsureYet);
writer.printf(" goto %s", falseLabel); this.right.codeGen(definitelyTrue, definitelyFalse);
} }
}

while
Negation

Kein zusätzlicher Bytecode-Befehl für logisch negierte Bedingungen, sondern Vertauschung while (x<10) {
der Sprungziele. Andere Strategien möglich, z. B. unter Verwendung “komplementärer” A
Vergleiche, z. B.  if_icmpge  statt  if_icmplt  für  !(x<y) . }

class UnOp extends Expr {


public void codeGen(String trueLabel, String falseLabel) { loopheader:
assert this.opType == UnOp.Type.NOT; iload 0 // x
this.operand.codeGen(falseLabel, trueLabel); bipush 10
} if_icmplt loopbody // falls kleiner, springe zu loopbody
} goto afterloop
loopbody:
A // Schleifenkörper
goto loopheader // springe zu nächster Iteration
afterloop:
// weitere Befehle

You might also like