Skip to content

Latest commit

 

History

History
233 lines (166 loc) · 4.8 KB

03_BasicTypesFunctionsAndOperators.md

File metadata and controls

233 lines (166 loc) · 4.8 KB

Basic Types, Functions and Operators

[ToC]

Simple Types

Hamler is strongly typed, and has a powerful static type system. Let's start with some simple examples.

Boolean

true :: Boolean
false :: Boolean

Numbers

Hamler has Integer and Float, and since they have different types so they can't be mixed.

--Integer
1 :: Integer

--Float
0.1 :: Float

Atoms

Atom is probably more familiar to Erlang user. It is a literal, a constant with a name starting with : .

:hello
:world

Strings

In Hamler String is just a list of Char

"Hello World" :: String  -- ['H','e','l','l','o',',','W','o','r','l','d']

Binaries

This is the very unique datatype that exists in Erlang. Binary contains the same information as ByteString and if you are not very familiar with binaries, this link should be helpful for some intuition.

<<1,2,3:8,4:16,5,"abcdefg">> :: Binary

Operators

Operator Meaning Operator Meaning
+ Numeric addition == Equality check
- Numeric subtraction < Less than
* Numeric multiplication <= Less than or equal
/ Numeric division (div) > Greater than
% Remainder >= Greater than or equal
&& Boolean AND || Boolean OR

Functions

When we define a new function, we can give it a type signature. For example double is a function takes an Integer and gives an Integer doubled as output.

double :: Integer -> Integer
double x = x * 2

Lambda Expression

There are also lambda expressions in Hamler, here is an example of how we rewrite double.

double' :: Integer -> Integer
double' = \x -> 2 * x

It becomes really handy when we need to make an anonymous function.

Currying

--Curry
--This is uncurried (+)
add :: (Integer, Integer) -> Integer
add (x, y) = x + y

--This is curried (+)
plus :: Integer -> Integer -> Integer
plus x y = x + y

Partial Application

-- plus :: Integer -> (Integer -> Integer) This is one of the example of higher order functions
>:t plus 2
plus 2:: Integer -> Integer
>let plusTwo = plus2
>plusTwo 3
5

Quantified Types

They are also known as polymorphic types.

> :type id
id :: forall a. a -> a

The key word forall indicates that id is univerally quantified, meaning that id can be applied to any type.

> id 1
1

A more complicated example is flip. flip is also a higher-order function, which will be explained in a later chapter.

> :type flip
forall a b c. (a -> b -> c) - > b -> a -> c

Notes On Indentations

Like a lot of ML based languages, Hamler is indentation sensitive. Any declaration in the same block should have the same level of indentation. In the case of a declaration spans more than one line, the other lines have to be intended past the first line.

flip x f = f
x                   -- NOT OKAY, Hamler will see x as a seperate declaration

flip f x = f
    x               -- OKAY, but not recommended

Let and Where Bindings

Keywords such as let and where introduce a new block, where further indentation is needed.

distance x y = sqrt z
  where
    z = x' + y'
    x' = x * x
    y' = y * y

Type Synonym

Type synonym can be used to simplify a long type name to make the code more readable.

>:i String
type String = [Char]

Or you can define you own synonym name or a record.

Records

type Name = String

type Person =
  { firstName  :: Name
  , secondName :: Name
  }

{-
This is syntax sugared
"type Person = Record (FirstName  :: Name , SecondName :: Name)"
-}

Fields can be accessed by .

leader :: Person
leader = {firstName = "John", lastName = "Portsman"}

>leader.firstName
"John"

This is how we update a record.

newLeader :: Person
newLeader = leader{firstName = "James"}

>newLeader.firstName
"James"
a = { name = "yang"
    , position =
         { streetNumber = 232
         , location = { x = 12.223
                      , y = 45.9 
                      }
         }
    }

b = a{position.location.x = 10.003}


> a.position.location.x
12.223
> b.position.location.x
10.003
a = { name = "yang"
    , pos ={ x = 10
           , y = 20
           , info = { s = "val"
                    , v = 45.9
                    }
           }
    }

b = a{pos.info.s = "newVal"}