Safe HaskellSafe-Inferred

Lessons.Lesson11

Description

Notes taken by Julija Mikeliūnaitė

Synopsis

Documentation

foo :: Integer Source #

Haskell has exceptions. The error function is the simplest way to throw exceptions. error is a pure function and can be any type. Here, the error function works as an integer, therefore it can be returned.

c :: Exception e => IO (Either e Integer) Source #

For exception cathcing you need the Control.Exception package. The try function needs an IO block.

eager :: [Integer] Source #

If the code is multithreaded, you can send exceptions to any thread.

Haskell is considered a lazy programming language. In a lazy language computations are only made if absolutely necessary.

If one of the items in the list is an error, the final result will be the error. This is an example of a strict/eager function.

>>> eager
oj

lazy :: [Integer] Source #

The take x function takes the first x elements from the list and returns them. This is an example of a lazy function.

>>> lazy
[1,2]

lazy' :: Int Source #

length is also a lazy function, because it counts how many items are in a list but does not care about their type (even if some of them may be errors).

>>> lazy'
1

lazy'' :: [Integer] Source #

With take 1, if the first element is an error, then the result is the error.

>>> lazy''
ooops

first :: Int -> [Integer] Source #

Even though the integer list is infinite, first 10 works fine, because of the laziness. If you were to print out the whole list [1..], it would just keep going forever to infinity.

>>> first 10
[1,2,3,4,5,6,7,8,9,10]

data Expr Source #

Lists are constructed using :, therefore the first n elements can be checked one by one.

Eager calculations - trying to compute all data at once and store everything in memory. It can be achieved using libraries with the keyword Strict.

seq function:

seq :: a -> b -> b Simplest explanation: the return value is bottom if a is bottom, otherwise it is b.

Returns 5 and ensures that everything was calculated/checked.

>>> seq 4 5
5

Returns 5, because seq removes the top layer of what is uncalculated.

>>> seq [error "Aj"] 5
5

Does all of the calculations, no matter the layer.

>>> deepseq ([error "Aj"]:: [Int]) 5
Aj

DSL - domain specific language. In our DSL's we had differend commands - a dictionary of tasks which we can use within our language. A classic example - calculator.

Expr (expression) can be either a literal (number) or an operation for two expressions (add, mul) or an operation for one expression (neg). This is already a DSL and now we can write programs using it.

Constructors

Lit Integer 
Add Expr Expr 
Mul Expr Expr 
Neg Expr 

Instances

Instances details
Show Expr Source # 
Instance details

Defined in Lessons.Lesson11

Methods

showsPrec :: Int -> Expr -> ShowS

show :: Expr -> String

showList :: [Expr] -> ShowS

prog1 :: Expr Source #

Program

eval :: Expr -> Integer Source #

This is used to define how the program should act with different expressions.

Evaluate >>> eval prog1 -15

print' :: Expr -> String Source #

This is used for printing different expressions to the console.

>>> print' prog1
"-(5 + 4 + 6)"

class Expression repr where Source #

If the grammar is not initial, it's either final or tagless final. Tagless - because it doesnt have tags (like lit, add and so on). FInal - because it is the final function. Classes are used to achieve this. Classes define what we can do with something and not how to construct a value. For example, the lit function takes an integer and returns its representation.

Methods

lit :: Integer -> repr Source #

add :: repr -> repr -> repr Source #

Instances

Instances details
Expression String Source #

You don't need to cover every instance for printing, it all depends on what you need for your project/business. lit = show, because lit a = show a is redundant since they both have the same signature.

Instance details

Defined in Lessons.Lesson11

Methods

lit :: Integer -> String Source #

add :: String -> String -> String Source #

Expression Integer Source #

The interpretor for the grammar.

Instance details

Defined in Lessons.Lesson11

Methods

lit :: Integer -> Integer Source #

add :: Integer -> Integer -> Integer Source #

class ExpressionMul repr where Source #

A new class is used to add multiplication.

Methods

mul :: repr -> repr -> repr Source #

Instances

Instances details
ExpressionMul Integer Source # 
Instance details

Defined in Lessons.Lesson11

Methods

mul :: Integer -> Integer -> Integer Source #

prog2 :: Integer Source #

Recreating prog1, just without negation; later we add multiplication.

>>> prog2
90

prog3 :: String Source #

Returns a string of the whole expression. >>> prog3 "5 + 4 + 6"

data GExpr a where Source #

This solves the issue with types by using multiple constructors.

Constructors

GInt :: Integer -> GExpr Integer 
GBool :: Bool -> GExpr Bool 
GAdd :: GExpr Integer -> GExpr Integer -> GExpr Integer 
GEq :: Eq a => GExpr a -> GExpr a -> GExpr Bool 

evalG :: GExpr a -> a Source #

You can't add GItn and GBool since they are of different types.

>>> evalG (GInt 5)
5
>>> evalG (GAdd (GInt 5) (GInt 6))
11
>>> evalG (GEq (GInt 5) (GInt 6))
False
>>> evalG (GAdd (GInt 5) (GBool False))
Couldn't match type `Bool' with `Integer'
Expected: GExpr Integer
  Actual: GExpr Bool
In the second argument of `GAdd', namely `(GBool False)'
In the first argument of `evalG', namely
  `(GAdd (GInt 5) (GBool False))'
In the expression: evalG (GAdd (GInt 5) (GBool False))