CS计算机代考程序代写 database crawler compiler Java Haskell ECS713-week06

ECS713-week06

Dr. Paulo Oliva / Prof. Edmund Robinson

Week 6: Input/Output in Haskell

ECS713
Functional Programming

Core Haskell / Types / IO Actions / Haskell “stack” Tool / Parsing
Core Haskell: Working with modules
– import modules using the “import” keyword
– organise your code into modules using the “module” keyword
Types: The “unit” type ()
– understand the role the unit type plays when working with IO actionsWeek 6/Task 1
IO Actions: Pure vs impure programming
– define the notion of computational “side effect”
– understand the difference between “pure” (no side effects) and “impure” (with side effects) programs
IO Actions: The IO type function
– familar with the basic Haskell functions that have IO type: print, putStrLn, readLnWeek 6/Task 1
– understand how impure programming in Haskell is controlled via the IO type functionWeek 6/Task 1
IO Actions: The “do” notation
– understand how IO action can be combined using the “do” notationWeek 6/Task 1
IO Actions: Working with files
– read contents from a text file (readFile), and and write to a text file (writeFile)Week 6/Task 1
Haskell “stack” Tool: Basic stack usage
– create a new project using “stack new”
– build an executable using “stack build”
Parsing: Recursive descent parsing
– understand the concept of “recursive descent parsing” and how it can be used to parse data defined
via context-free grammars

http://learnyouahaskell.com/modules#loading-modules
http://learnyouahaskell.com/modules#making-our-own-modules
https://en.wikipedia.org/wiki/Unit_type
https://livebook.manning.com/book/functional-programming-in-c-sharp/chapter-2/12
https://livebook.manning.com/book/functional-programming-in-c-sharp/chapter-2/12
http://learnyouahaskell.com/input-and-output
http://learnyouahaskell.com/input-and-output
http://learnyouahaskell.com/a-fistful-of-monads#do-notation
http://learnyouahaskell.com/input-and-output#files-and-streams
https://docs.haskellstack.org/en/stable/README/#quick-start-guide
https://docs.haskellstack.org/en/stable/README/#quick-start-guide
https://www.cmi.ac.in/~spsuresh/teaching/prgh15/papers/monadic-parsing.pdf
https://www.cmi.ac.in/~spsuresh/teaching/prgh15/papers/monadic-parsing.pdf
https://www.cmi.ac.in/~spsuresh/teaching/prgh15/papers/monadic-parsing.pdf

stack

stack

• Cross-platform program for Haskell projects
• Tackle common build issues in Haskell
• Around since June of 2015
• A .cabal file for each package defines package-

level metadata (stack uses cabal)

• A stack.yaml file provides information on where
dependencies come from

stack – basic usage

$ stack new helloworld new-template

Create new project:

$ stack setup

Configure new project: (cd into new folder)

$ stack build

Build executable:

$ stack exec helloworld-exe

Run your program

stack – basic usage

$ stack new helloworld

Create new project (omit template for standard
project):

$ stack setup

Stack setup installs the appropriate ghc for the
project.

$ stack build

Build executable:

$ stack ghci

Run ghci

stack – project layout
Edmunds-MacBook-Pro:tmp edmundr$ tree demo
demo
├── ChangeLog.md
├── LICENSE
├── README.md
├── Setup.hs
├── app
│   └── Main.hs
├── demo.cabal
├── package.yaml
├── src
│   └── Lib.hs
├── stack.yaml
└── test
└── Spec.hs

3 directories, 10 files

Main Program

Project library files

Library module file

Directory for test
suite

stack – build files
Edmunds-MacBook-Pro:tmp edmundr$ tree demo
demo
├── ChangeLog.md
├── LICENSE
├── README.md
├── Setup.hs
├── app
│   └── Main.hs
├── demo.cabal
├── package.yaml
├── src
│   └── Lib.hs
├── stack.yaml
└── test
└── Spec.hs

3 directories, 10 files

cabal package

stack project

.yaml vs .cabal
• A project can have multiple packages
• Each project has a stack.yaml
• Each package has a .cabal file
• The .cabal file specifies which packages are

dependencies

• stack.yaml specifies which packages are available
• .cabal specifies the components, modules, and

build flags provided by a package

• stack.yaml specifies which packages to include

.Modules, packages, projects

• A module is a single source file

• It contains declarations, and an export list

• The name of the module is basically the name
of the file

• Modules are the units Haskell uses to import
code into programs

• The Haskell language knows about modules,
but not packages or projects

• Module: Haskell

• Package: Cabal

• Project: Stack

Creating Modules

— file: CrawlerDB.hs

module CrawlerDB ( printURLs ) where

import CrawlerHTTP
import Database.HDBC
import Database.HDBC.Sqlite3

printURLs :: IO ()
printURLs = do urls <- getURLs mapM_ print urls getURLs :: IO [URL] getURLs = do conn <- connectSqlite3 "urls.db" res <- quickQuery' conn "SELECT url FROM urls" [] return $ map fromSql (map head res) module name should be the same as file name exported functions function only used locally Using Modules -- file: CrawlerDB.hs module CrawlerDB ( printURLs ) where import CrawlerHTTP import Database.HDBC as Db import Database.HDBC.Sqlite3 (connectSQlite3) printURLs :: IO () printURLs = do urls <- getURLs mapM_ print urls getURLs :: IO [URL] getURLs = do conn <- connectSqlite3 "urls.db" res <- quickQuery' conn "SELECT url FROM urls" [] return $ map fromSql (map head res) modules are imported through import directives rename module import list Importing Modules import Data.List -- import all import Data.List (words, sort) -- selective import import Data.List hiding (sort) -- import all except sort Dealing with name clashes import qualified Data.Map -- call as Data.Map.filter import qualified Data.Map as M -- call as M.filter .Modules, packages, projects • A package is a library of Haskell modules known to the compiler • Cabal is a system for building and packaging Haskell libraries and programs. • The build of each package is controlled by a “cabal” file. • Packages have to be installed and registered in a database in order to be usable by the compiler. • Packages are identified by a base name and version number: • The Haskell language knows about modules, but not packages or projects • Module: Haskell • Package: Cabal • Project: Stack .Modules, packages, projects • Module: Haskell • Package: Cabal • Project: Stack .Modules, packages, projects • Module: Haskell • Package: Cabal • Project: Stack .Modules, packages, projects • Stack deals with projects • A project can contain multiple packages, but may just contain one. • The build of a project is controlled by a “stack.yaml” file. • The stack.yaml file specifies which packages to build, and where to get library files from if they are needed. • Module: Haskell • Package: Cabal • Project: Stack stack.yaml # file stack.yaml ... # Resolver to choose a 'specific' stackage snapshot or a compiler version. # A snapshot resolver dictates the compiler version and the set of packages # to be used for project dependencies. For example: # # resolver: lts-3.5 # resolver: ghc-7.10.2 resolver: lts-3.5 ... # Packages to be pulled from upstream that are not in the resolver extra-deps: - HTTP-4000.3.3 http://docs.haskellstack.org/en/stable/yaml_configuration/ resolver containing curated package set package and version helloworld.cabal name: helloworld version: 0.1.0.0 ... library hs-source-dirs: src exposed-modules: Lib build-depends: base >= 4.7 && < 5 , text , HTTP default-language: Haskell2010 ... source-repository head type: git location: https://github.com/githubuser/helloworld https://docs.haskellstack.org/en/stable/GUIDE/#stackyaml-vs-cabal-files package names, sometimes with version constraints stack on ITL • Use Linux • First time run $ stack-check • Will create symbolic link /home/USER/.stack -> /import/scratch/ECS713P_stack

• From there on use stack as “normal”

Input/Output in Haskell

Pure versus Impure

Pure Impure

Definitions Commands

Stateless State (e.g. global variables)

No side effects Side effects

Easy to reason
about program

Easy to interact with
outside world

Pure versus Impure

Pure Impure

Definitions Commands

Stateless State (e.g. global variables)

No side effects Side effects

Easy to reason
about program

Easy to interact with
outside world

Pure versus Impure

Pure Impure

Definitions Commands

Stateless State (e.g. global variables)

No side effects Side effects

Easy to reason
about program

Easy to interact with
outside world

Contained in IO
types

Algebraic Types
Just like functions, our algebraic type can

be parametrised by another type

data Maybe a = Nothing | Just a
data Either a b = Left a | Right b

— Maybe is often used when a value might not be available
first :: [a] -> Maybe a
first [] = Nothing
first (x:xs) = Just x

You call these “type functions”

RE
CA

P

The IO Type Function

IO a
We call the type “IO a” an “IO action of type a”.
When performed it might carry out an action with

side-effect and yield a result of type a.

IO Int IO Bool IO [Char] IO ()

For instance, we could have: the “unit” type

IO is a (special) type function

The unit type ( )

Prelude> :type ()

() :: ()

() is the type containing only
one element, namely ()

It plays the role of “void” in
languages such as C and Java

Hence, a function that is only meant
to do an IO action but not return any
value will have return type “IO ()”

Prelude> :type print

print :: Show a => a -> IO ()

The IO Type Function
IO type is used for operations that
interact with the “outside world”

Prelude> :type print

print :: Show a => a -> IO ()

Prelude> :type readFile

readFile :: FilePath -> IO String

Prelude> :type getLine

getLine :: IO String

given something that can
be “shown”, shows it on
screen and returns ()

given a file path, reads
contents of the file and
returns this content

reads one line of user
input and returns that
list of characters

The IO Type Removal Question
IO type is used for operations that
interact with the “outside world”

Prelude> getLine

hello

“hello”

Prelude> length getLine

:17:1: error:

length only applies
to pure Strings

getLine
is an

IO String

What function can I apply to my IO String to
extract the String???

The IO Type Removal Answer

Prelude> getLine

hello

“hello”

Prelude> length getLine

:17:1: error:

length only applies
to pure Strings

getLine
is an

IO String

What function can I apply to my IO String to
extract the String???

Answer: there isn’t one

And that is deliberate!

The IO Type Removal Answer

Prelude> getLine

hello

“hello”

Prelude> length getLine

:17:1: error:

length only applies
to pure Strings

getLine
is an

IO String

What function can I apply to my IO String to
extract the String???

Anything acquired through an IO action stays in
IO type

It is forever tainted!

But you can unpack it locally inside a do
block.

Greeting Example
— file: week06.hs

main = do

putStrLn “Greetings! What is your name?”

x <- getLine putStrLn $ "Welcome to Haskell, " ++ x ++ "!" $ runghc week06.hs Greetings! What is your name? Paulo Welcome to Haskell, Paulo! “do” glues IO actions together type of the whole action is the type of the last action I/O Actions x <- getLine 1. perform this action 2. bind this name to the returning value The “do” block automatically extracts the value of the last action and returns that as its own result readFile / writeFile import System.IO import Data.Char main = do contents <- readFile "poem.txt" writeFile "poem-cap.txt" (map toUpper contents) To be or not to be that’s the question poem.txt TO BE OR NOT TO BE THAT’S THE QUESTION poem-cap.txt readFile :: FilePath -> IO String
writeFile :: FilePath -> String -> IO ()