Haskell Scripts

HaskellScripts
YanHuang
[email protected]
LastQuiz
Objectives
• WritingHaskellprogramsin“.hs”files
• NotesomedifferencesbetweenprogramstypedintoGHCi and
programswritteninscriptfiles
• OperatorPrecedence
• OperatorAssociativity
HaskellScripts
• Aswellasthefunctionsinthestandardlibrary,youcanalsodefine
yourownfunctions;
• Newfunctionsaredefinedwithinascript,atextfilecomprisinga
sequenceofdefinitions;
• Byconvention,Haskellscriptsusuallyhavea.hs suffixontheir
filename.
MyFirstScript
WhendevelopingaHaskellscript,itisusefultokeep
twowindowsopen,onerunninganeditorforthe
script,andtheotherrunningGHCi.
Startaneditor,typeinthefollowingtwofunction
definitions,andsavethescriptastest.hs:
double x
= x + x
quadruple x = double (double x)
Leavingtheeditoropen,inanotherwindowstartup
GHCi withthenewscript:
$ ghci test.hs
Nowboththestandardlibraryandthefiletest.hs are
loaded,andfunctionsfrombothcanbeused:
> quadruple 10
40
> take (double 2) [1,2,3,4,5,6]
[1,2,3,4]
LeavingGHCi open,returntotheeditor,addthe
followingtwodefinitions,andsave:
factorial n = product [1..n]
average ns = sum ns `div` length ns
Note:
z div isenclosedinback quotes,notforward;
z x `f` y isjustsyntacticsugar forf x y.
GHCi doesnotautomaticallydetectthatthescripthas
beenchanged,soareload commandmustbeexecuted
beforethenewdefinitionscanbeused:
> :reload
Reading file "test.hs"
> factorial 10
3628800
> average [1,2,3,4,5]
3
UsefulGHCiCommands
Command
Meaning
:load name
:reload
:type expr
:?
:quit
load script name
reload current script
show type of expr
show all commands
quit GHCi
:set editor name
:edit name
:edit
set editor to name
edit script name
edit current script
NamingRequirementsandConventions
• Functionandargumentnamesmustbeginwitha
lower-caseletter.Forexample:
myFun
fun1
arg_2
x’
Byconvention,listargumentsusuallyhaveanssuffix
ontheirname.Forexample:
xs
ns
nss
TheLayoutRule
Inasequenceofdefinitions,eachdefinitionmustbegin
inpreciselythesamecolumn:
a = 10
b = 20
c = 30
a = 10
b = 20
c = 30
a = 10
b = 20
c = 30
Thelayoutruleavoidstheneedforexplicitsyntaxto
indicatethegroupingofdefinitions.
a = b + c
where
b = 1
c = 2
d = a * 2
implicitgrouping
means
{a = b + c
where
{b = 1;
c = 2}
d = a * 2}
explicitgrouping
In script:
In GHCi:
a = 1
let a = 1
Operators
Prelude λ: 3+5
Prelude λ: mod 3 5
8
3
Prelude λ: (+) 3 5
Prelude λ: 3 `mod` 5
8
3
Prelude λ: 3 / 5
Prelude λ: 2 `elem` [1,2,3]
0.6
True
Prelude λ: (/) 3 5
Prelude λ: elem 2 [1,2,3]
0.6
True
• Operatorsareinessence
functions.
• Operatorswhoseidentifiers
consistofsymbolsareby
defaultinfix.Surroundthem
withparentheses touseas
prefixoperators.
• Operatorswithlettersintheir
identifiersareprefix by
default.Placetheminbackquotestouseasinfix
operators.
Prelude λ: :info +
OperatorPrecedence
3+5∗2
class Num a where
(+) :: a -> a -> a
...
-- Defined in ‘GHC.Num’
infixl 6 +
Prelude λ: :info *
class Num a where
...
“∗”hashigherprecedencethan“+”
(*) :: a -> a -> a
...
-- Defined in ‘GHC.Num’
infixl 7 *
OperatorPrecedence
+ 3 5∗2
• Prefixform(+)istreatedasnormalfunction(precedenceescalatedto
thatoffunctionapplications,whichishigherthan‘*’)
• Infix+isprocessedasnormalbinaryoperators
PrecedenceandAssociativityofSelectedOperators
Left-associative
9
Non-associative
!!
Right-associative
.
8
^, ^^, **
7
*, /, `div`
6
+, -,
5
:, ++
==, /=, >, >=, <, <=
`elem`, `notElem`
4
3
&&
2
||
1
0
>>, >>=
$, $!, `seq`
• Functionapplicationsareoflevel10precedence.
• Anyoperatorlackingafixitydeclarationisassumedtobe infixl 9.
!!
*Main λ: :type (!!)
(!!) :: [a] -> Int -> a
.
*Main λ: :type (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
^,^^,**
*Main λ: :type (^)
(^) :: (Integral b, Num a) => a -> b -> a
*Main λ: :type (^^)
(^^) :: (Fractional a, Integral b) => a -> b -> a
*Main λ: :type (**)
(**) :: Floating a => a -> a -> a
*, /, `div`
*Main λ: :type (*)
(*) :: Num a => a -> a -> a
*Main λ: :type (/)
(/) :: Fractional a => a -> a -> a
*Main λ: :type div
div :: Integral a => a -> a -> a
+,-
:,++
*Main λ: :type (:)
(:) :: a -> [a] -> [a]
*Main λ: :type (++)
(++) :: [a] -> [a] -> [a]
==,/=,>,>=,<,<=
`elem`,`notElem`
*Main λ: :type elem
elem :: (Eq a, Foldable t) => a -> t a -> Bool
*Main λ: :type notElem
notElem :: (Eq a, Foldable t) => a -> t a -> Bool
&&
*Main λ: :type (&&)
(&&) :: Bool -> Bool -> Bool
||
>>, >>=
*Main λ: :t (>>)
(>>) :: Monad m => m a -> m b -> m b
*Main λ: :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
$, $!,`seq`
*Main λ: :info ($)
($) :: (a -> b) -> a -> b
-- Defined in ‘GHC.Base’
infixr 0 $
*Main λ: :info ($!)
($!) :: (a -> b) -> a -> b
-- Defined in ‘GHC.Base’
infixr 0 $!
*Main λ: :info seq
seq :: a -> b -> b
infixr 0 `seq`
-- Defined in ‘GHC.Prim’
Non-AssociativeOperators
==,/=,>,>=,<,<=
`elem`,`notElem`
Prelude λ: True == False
False
Prelude λ: True == False == False
<interactive>:551:1:
Precedence parsing error
cannot mix ‘==’ [infix 4] and ‘==’ [infix 4] in the same infix expression
OperatorAssociativity
• Associatetotheleft
1+2+35-4-318/9/1
OperatorAssociativity
• Associatetotheright
5^3^2
Prelude λ: :info ^
(^) :: (Num a, Integral b) => a -> b -> a -- Defined in ‘GHC.Real’
infixr 8 ^
1:2:3:[]
Prelude λ: :info :
data [] a = ... | a : [a]
infixr 5 :
-- Defined in ‘GHC.Types’
OperatorPrecedenceandAssociativity
f gx ≢fgx
f gx ≡f$gx
CustomizingPrecedenceandAssociativity
multThenInc :: Int -> Int -> Int
multThenInc x y = x * y + 1
infix 3 @@
(@@) = multThenInc
@@operatorhasprecedencelevel3,non-associative.
@@isabinaryfunctiononInt asspecifiedbymultThenInc.
OperatorPrecedenceandAssociativity
5^3-1^2:2^3*3`div`2:3+5:3+2^3`div`2+3:[]
Exercises
(1) Fixthesyntaxerrorsintheprogrambelow,and
testyoursolutionusingGHCi.
N = a ’div’ length xs
where
a = 10
xs = [1,2,3,4,5]
(2) Showhowthelibraryfunctionlast thatselects
thelastelementofalistcanbedefinedusingthe
functionsintroducedinthislecture.
(3) Canyouthinkofanotherpossibledefinition?
(4) Similarly,showhowthelibraryfunctioninit
thatremovesthelastelementfromalistcanbe
defined(possiblyintwodifferentways).
(5) Whatdoes1 @@ 2 @@ 3 + 4 evaluatetounder
thefollowingthreedefinitions?Explain.
multThenInc :: Int -> Int -> Int
multThenInc x y = x * y + 1
multThenInc :: Int -> Int -> Int
multThenInc x y = x * y + 1
multThenInc :: Int -> Int -> Int
multThenInc x y = x * y + 1
infixl 3 @@
(@@) = multThenInc
infixl 7 @@
(@@) = multThenInc
infix 5 @@
(@@) = multThenInc
(6) Whatdo1 @@ 2 @@ 3,
1 == 2 == 2,
3 @@ 5 == 1 evaluateto,respectively?Explain.