:i
- display the definition of a function, typeclass, or type:t
- display the type of an expression:k
- display the kind of a type:l
- load a program (a source file):r
- reload the loaded program
()
- unit type, similar toVoid
in other languages.- The unit type can have only one value - the unit value
()
(similar to an empty tuple)
_
- wildcard character that matches any value
mkValidator :: Data -> Data -> Data -> ()
mkValidator
- function nameData -> Data -> Data
- three parameters()
- return type- In Haskell all functions with multiple parameters are curried, which allows partial application
mkValidator _ _ _ = ()
mkValidator
- function name_ _ _
- three arguments (ignored with wildcards)()
- return value
error :: () -> a
a
- any type, similar to generics in other languages
Haskell data types are similar to struct
and value types in other languages.
data Data =
Constr Integer [Data]
| Map [(Data, Data)]
| List [Data]
| I Integer
| B BS.ByteString
deriving stock (Show, Eq, Ord, Generic)
deriving anyclass (NFData)
data
- define a new data type=
- everything after=
are constructorsConstr
- constructor nameInteger [Data]
- constructor parameters|
- separates multiple constructorsMap
,List
,I
,B
- other constructor namesderiving
- see [[#Typeclasses]]
newtype MySillyRedeemer = MySillyRedeemer Integer
newtype
- special case ofdata
declaration that permits only one constructor and only one parameterMySillyRedeemer
- nameMySillyRedeemer Integer
- constructor
type POSIXTimeRange = Interval POSIXTime
type
- define a type synonym (i.e., alias) for the specified data typeInterval
- data type declared asInterval a
POSIXTime
- type argument fora
inInterval
declaration
Haskell typeclass
(or the shorthand class
) is similar to interface
, protocol
or trait
in other languages.
class ValidatorTypes (a :: Type) where
type RedeemerType a :: Type
type DatumType a :: Type
class
- declare a new typeclassValidatorTypes
- typeclass name(a :: Type)
- type variabletype
- declare an associated type synonym (see type families)RedeemerType
- type synonym name
data Typed
instance Scripts.ValidatorTypes Typed where
type instance DatumType Typed = ()
type instance RedeemerType Typed = Integer
instance
- declare the data type as an instance of the specified typeclass, similar tointerface
orprotocol
implementation in other languages.Scripts.ValidatorTypes
- typeclassTyped
- type the instance is being provided forwhere
- terminates the initial declaration and follows up with the implementation
data Data =
Constr Integer [Data]
| Map [(Data, Data)]
| List [Data]
| I Integer
| B BS.ByteString
deriving stock (Show, Eq, Ord, Generic)
deriving anyclass (NFData)
deriving
- automatically make this type an instance of the specified typeclassesstock, anyclass
- deriving strategies(Show, Eq, Ord, Generic)
- typeclasses to be derived
mkValidator :: Data -> Data -> Data -> ()
mkValidator _ r _
| r == I 42 = ()
| otherwise = traceError "wrong redeemer"
|
- guard caser == I 42
- expression used to test this case (must evaluate toBool
)= ()
- expression to be evaluated and returned, if the test isTrue
otherwise
- default case which always evaluates toTrue
- Guards without pattern matching are similar to
if-else
statements in other languages. - Guard with pattern matching are similar to
switch
statements in other languages.
typedValidator :: Scripts.TypedValidator Typed
typedValidator = Scripts.mkTypedValidator @Typed
$$(PlutusTx.compile [|| mkValidator ||])
$$(PlutusTx.compile [|| wrap ||])
where
wrap = Scripts.wrapValidator @() @Integer
where
- allows to define local functions and constantswhere
definitions are bound to the current function
traceIfFalse "wrong redeemer" $ r == 42
Equivalent to:
traceIfFalse "wrong redeemer" (r == 42)
$
is an infix version of function application($) :: (a -> b) -> a -> b
$
allows to avoid parentheses by separating expressions and giving precedence to anything after it.$
has right associativity and the lowest precedence possible - 0, whereas normal function application is left associative and has the highest precedence possible - 10.
{-# INLINABLE mkValidator #-}`
{-# ... #-}
- pragmas are instructions to the compiler (they affect the generated code)
Template Haskell is used for compile-time metaprogramming.
$$(PlutusTx.compile [|| mkValidator ||])
- AST - Abstract Syntax Tree
[|| ... ||]
- typed expression quotation, quotes the expression and produces the AST of it (Q Exp
)$$(...)
- typed expression splice, converts from the AST to the expression
PlutusTx.unstableMakeIsData ''MySillyRedeemer
''
- quote a type name,''MySillyRedeemer
has typeName
.Name
is used to construct Template Haskell expressions, patterns, declaration, etc.
$$(PlutusTx.compile [|| mkValidator ||]) `PlutusTx.applyCode` PlutusTx.liftCode p
Equivalent to:
PlutusTx.applyCode $$(PlutusTx.compile [|| mkValidator ||]) (PlutusTx.liftCode p)
`PlutusTx.applyCode`
- infix function application
validator = Scripts.validatorScript . typedValidator
Equivalent to:
validator p = Scripts.validatorScript $ typedValidator p
(.) :: (b -> c) -> (a -> b) -> a -> c
- given a functionb
toc
and a functiona
tob
, return a functiona
toc
.(f . g) x = f (g x)
- wheref
corresponds tob -> c
andg
toa -> b
..
is an infix operator with right associativity and the precedence of 9 (out of 10) (normal function application is left associative and has the highest precedence possible - 10; therefore, composed functions should be enclosed in parentheses for application or applied with$
operator -(negate . sum) [1, 2, 3]
ornegate . sum $ [1,2,3]
).
fmap :: Functor f => (a -> b) -> f a -> f b
Functor f
before=>
is a typeclass constraint, which restricts the type off
to instances of theFunctor
typeclass.
Functor
is a typeclass that declares fmap
function.
The idea of a functor is to bring the convenience of map
to non-collection types. In the same way as map
function allows to transform the contents of a collection, fmap
function can transform the contents of any container that implements Functor
typeclass.
Functor laws:
- Identity:
fmap id == id
- Composition:
fmap (f . g) == fmap f . fmap g
> fmap (map toUpper) getLine
Haskell
"HASKELL"
fmap
- similar tomap
, but applied to functors.fmap :: Functor f => (a -> b) -> f a -> f b
(a -> b)
- transformation function froma
tob
f a
- functor that containsa
f b
- resulting functor that will containb
after applying the transformation function(a -> b)
<$>
- infix version offmap
function(<$>) :: Functor f => (a -> b) -> f a -> f b
$
in the name alludes to [[#Function application operator]]
Applicative
is a typeclass that declares pure
function and <*>
operator. Any Applicative
instance is also Functor
instance.
The idea of an applicative functor is to allow to apply a transformation function contained in one container to the contents of another container. The difference between fmap
(<$>
) and <*>
is that (a -> b)
transformation function is now inside a container.
pure
- lifts (i.e., wraps) a type into the applicative structure
pure :: Applicative f => a -> f a
> pure (+1) <*> [1..3]
[2,3,4]
Equivalent to:
> (+1) <$> [1, 2, 3]
[2,3,4]
> fmap (+1) [1, 2, 3]
[2,3,4]
<*>
- similar tofmap
, but transformation function is inside an applicative functor<*> :: Applicative f => f (a -> b) -> f a -> f b
f (a -> b)
- applicative functor that contains a transformation function froma
tob
f a
- applicative functor which contents will transformedf b
- resulting applicative functor
Monad
is a typeclass that declares >>
and >>=
operators. Any Monad
instance is also Applicative
and Functor
instance.
The idea of a monad is to avoid unwrapping values inside a container before passing them to a function that takes such values and returns them after transformation inside a container of the same type.
return
- lifts a type into the monad structure, similar topure
function ofApplicative
.return :: Monad m => a -> m a
> putStrln "Hello" >> putStrln "World"
Hello
World
>>
- sequences two actions and discards the result of the first action(>>) :: Monad m => m a -> m b -> m b
> getLine >>= putStrLn
Haskell
Haskell
>>=
is similar toflatMap
function in other languages.>>=
- binds a monad containing valuea
to a function that takes valuea
and returns it transformed tob
inside a monad of the same type.(>>=) :: Monad m => m a -> (a -> m b) -> m b
main :: IO ()
main = putStrln "Hello World!"
The idea of IO
is to have a container in which interaction with real world can happen, whereas everything outside IO
can stay pure (i.e., side effect free).
IO
is a type that hasMonad
instanceIO
execution is allowed to have side effectsIO
can be executed inmain
or REPL.
> readMaybe "42" :: Maybe Int
Maybe
is a data type similar toOptional
in other languages.Maybe
hasMonad
instancedata Maybe a = Nothing | Just a
readEither :: Read a => String -> Either String a
readEither s = case readMaybe s of
Nothing -> Left $ "can't parse: " ++ s
Just a -> Right a
Either
is a data type similar toResult
in other languages, but more generic.Either
hasMonad
instancedata Either a b = Left a | Right a
bar :: IO ()
bar = getLine >>= \s -> getLine >>= \t -> putStrLn (s ++ t)
\s
- is a parameter of the anonymous function\
- is an allusion to λ symbol in lambda abstractions
foo :: String -> String -> String -> Maybe Int
foo x y z = case readMaybe x of
Nothing -> Nothing
Just k -> case readMaybe y of
Nothing -> Nothing
Just l -> case readMaybe z of
Nothing -> Nothing
Just m -> Just (k + l + m)
- Similar to pattern matching using
switch
expression in other languages. case readMaybe x of
-readMaybe x
is the expression to be matched.Nothing -> Nothing
- pattern to matchNothing
inMaybe
and returnNothing
.Just k -> case readMaybe y of
- pattern to match valuek
inMaybe
and return another case expression.
bindMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b
bindMaybe Nothing _ = Nothing
bindMaybe (Just x) f = f x
- Functions can have separate function definitions for different patterns.
bindMaybe Nothing _
- define a function body for the case when the first argument is matchingNothing
.bindMaybe (Just x) f
- define a function body for the case when the first argument is matchingJust x
(Maybe
contains valuex
).
foo :: Writer Int -> Writer Int -> Writer Int -> Writer Int
foo (Writer k xs) (Writer l ys) (Writer m zs) =
let
s = k + l + m
Writer _ us = tell ["sum: " ++ show s]
in
Writer s $ xs ++ ys ++ zs ++ us
let ...
- define variablesin ...
- expression in which defined variables are used
threeInts' :: Monad m => m Int -> m Int -> m Int -> m Int
threeInts' mx my mz = do
k <- mx
l <- my
m <- mz
let s = k + l + m
return s
Equivalent to:
threeInts :: Monad m => m Int -> m Int -> m Int -> m Int
threeInts mx my mz =
mx >>= \k ->
my >>= \l ->
mz >>= \m ->
let s = k + l + m in return s
- Do notation is a syntactic convenience for sequencing actions
- When using
let
inside ado
block,in
is not needed k <- mx
- bind the result ofmx
to the variablek
foo'' :: Writer Int -> Writer Int -> Writer Int -> Writer Int
foo'' x y z = do
s <- threeInts x y z
tell ["sum: " ++ show s]
return s
tell ["sum: " ++ show s]
- execute action without binding it to a variable
Monoid
is a typeclass that declares mempty
and mappend
functions. Any Monoid
instance is also Semigroup
instance. The most common example of a monoid is a list.
Monoid laws:
- Binary operation - operates on two values
- Associative - the order of evaluation doesn't matter
- Identity - there exists a neutral value (when combined with any other value, will return the other value)
mempty :: a
- returns the identity value
mappend :: a -> a -> a
- joins two values together
element : list
:
- add an element to the start of a list.
list ++ [element]
++
- add an element to the end of a list.
> head [1,2,3]
1
head
- return the first element.
> tail [1,2,3]
[2,3]
tail
- return all elements without the first one.
> init [1,2,3]
[1,2]
init
- return a new list without the last element.
> null []
True
> null [1,2,3]
False
null
- return whether the list is empty.
Void
cannot have a value (whereasUnit
has one value only), similar toNever
in other languages.