Odds and Ends
This presentation is the property of its rightful owner.
Sponsored Links
1 / 23

Odds and Ends in Haskell: Folding, I/O, and Functors PowerPoint PPT Presentation


  • 81 Views
  • Uploaded on
  • Presentation posted in: General

Odds and Ends in Haskell: Folding, I/O, and Functors. Adapted from material by Miran Lipovaca. The foldl function. We’ve seen a particular pattern quite often with lists: - base case on empty list - some operation with the head, plus a recursive call on the tail

Download Presentation

Odds and Ends in Haskell: Folding, I/O, and Functors

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Odds and ends in haskell folding i o and functors

Odds and Ends

in Haskell:

Folding, I/O, and Functors

Adapted from material by Miran Lipovaca


The foldl function

The foldl function

We’ve seen a particular pattern quite often with lists:

- base case on empty list

- some operation with the head, plus a recursive

call on the tail

This is such a common pattern that there is a higher-order function to handle it.

Inputs: a function, a initial starting value (which we’ll call the accumulator, although it can have any name) and a list to “fold up”


Odds and ends in haskell folding i o and functors

Example: implementing the sum function

sum'::(Numa)=>[a]->a

sum'xs=foldl(\accx-> acc +x)0 xs

The binary function is applied to the accumulator and the first element (in foldl), and produces a new accumulator. Then called again with the new accumulator and the new first element of the list, until the rest of the list is empty.

ghci>sum'[3,5,2,1]

11


Odds and ends in haskell folding i o and functors

In fact, we can write this function in an even shorter way, since functions can be returned as parameters:

sum'::(Numa)=>[a]->a

sum'=foldl(+)0

The lambda function on the previous slide is really the same as (+), and we can omit xs because the function written above will just return a function that takes a list as input.


Odds and ends in haskell folding i o and functors

Another example: elem

Returns True if the variable is present in the list

elem'::(Eqa)=>a->[a]->Bool

elem'yys=foldl

(\accx>ifx==ythenTrueelseacc)

Falseys

  • - Starting value and accumulator are booleans.

  • Start (and default) is False, which makes sense.

  • Check if current element is what we want. If so,

  • done (so return True). Otherwise, accumulator is unchanged, and it continues on with the tail.

4


Odds and ends in haskell folding i o and functors

Other functions:

- Foldr is the same, except starts with the end of the list (and accumulator is the second input to the function).

- Scanl and scanr work just the same, but return all intermediate accumulator values in a list.

- foldl1 and foldr1 work just the same as foldl and foldr, but don’t need to provide a starting value - they assume first (or last) element of the list is the starting value.


File i o

File I/O

So far, we’ve worked mainly at the prompt, and done very little true input or output. This is logical in a functional language, since nothing has side effects!

However, this is a problem with I/O, since the whole point is to take input (and hence change some value) and then output something (which requires changing the state of the screen or other I/O device.

Luckily, Haskell offers work-arounds that separate the more imperative I/O.


Odds and ends in haskell folding i o and functors

A simple example: save the following file as helloword.hs

main=putStrLn"hello,world"

Now we actually compile a program:

$ghc--makehelloworld

[1of1]CompilingMain

(helloworld.hs,helloworld.o)

Linkinghelloworld...

$./helloworld

hello,world

7


Odds and ends in haskell folding i o and functors

What are these functions?

ghci>:tputStrLn

putStrLn::String->IO()

ghci>:tputStrLn"hello,world"

putStrLn"hello,world"::IO()

So putStrLn takes a string and returns an I/O action (which has a result type of (), the empty tuple).

In Haskell, an I/O action is one with a side effect - usually either reading or printing. Usually some kind of a return value, where () is a dummy value for no return.

8


Odds and ends in haskell folding i o and functors

An I/O action will only be performed when you give it the name “main” and then run the program.

A more interesting example:

main=do

putStrLn"Hello,what'syourname?”  

name<-getLine

putStrLn("Hey"++name++",

yourock!")

Notice the do statement - more imperative style.

Each step is an I/O action, and these glue together.

9


Odds and ends in haskell folding i o and functors

More on getLine:

ghci>:tgetLine

getLine::IOString

This is the first I/O we’ve seen that doesn’t have an empty tuple type - it has a String.

Once the string is returned, we use the <- to bind the result to the specified identifire.

Notice this is the first non-functional action we’ve seen, since this function will NOT have the same value every time it is run! This is called “impure” code.

10


Odds and ends in haskell folding i o and functors

An invalid example:

nameTag="Hello,mynameis"++getLine

What’s the problem? Well, ++ requires both parameters to have the same type.

What is the return type of getLine?

Another word of warning: what does the following do?

name=getLine

11


Odds and ends in haskell folding i o and functors

  • Just remember that I/O actions are only performed in a few possible places:

  • A main function

  • inside a bigger I/O block that we have composed with a do (and remember that the last action can’t be bound to a name, since that is the one that is the return type).

  • At the ghci prompt:

ghci>putStrLn"HEEY"

HEEY

12


Odds and ends in haskell folding i o and functors

You can use let statements inside do blocks, to call other functions (and with no “in” part required):

importData.Char

main=do

putStrLn"What'syourfirstname?"

firstName<-getLine

putStrLn"What'syourlastname?"

lastName<-getLine

letbigFirstName=maptoUpperfirstName

bigLastName=maptoUpperlastName

putStrLn$"hey"++bigFirstName++""++

bigLastName++",howareyou?"

Note that <- is for I/O, and let for expressions.

13


Odds and ends in haskell folding i o and functors

Return in haskell: NOT like other languages.

main=do

line<-getLine

ifnullline

thenreturn()

elsedo

putStrLn$reverseWordslinemain

reverseWords::String->String

reverseWords=unwords

mapreverse.words

14


Odds and ends in haskell folding i o and functors

What is return?

Does NOT signal the end of execution! Return instead makes an I/O action out of a pure value.

main=do

a<-return"hell"

b<-return"yeah!"

putStrLn$a++""++b

In essence, return is the opposite of <-. Instead of “unwrapping” I/O Strings, it wraps them.

15


Odds and ends in haskell folding i o and functors

  • Other I/O functions:

  • print (works on any type in show, but calls show first)

  • putStr - And as putStrLn, but no newline

  • putChar and getChar

main=doprintTrue

print2

print"haha"

print3.2

print[3,4,3]

main=do

c<-getChar

ifc/=''

thendo

putCharc

main

elsereturn()

16


Odds and ends in haskell folding i o and functors

More advanced functionality is available in Control.Monad:

importControl.Monad

importData.Char

main=forever$do

putStr"Givemesomeinput:"

l<-getLine

putStrLn$maptoUpperl

(Will indefinitely ask for input and print it back out capitalized.)

17


Functors

Functors

Functors are a typeclass, just like Ord, Eq, Show, and all the others. This one is designed to hold things that can be mapped over; for example, lists are part of this typeclass.

classFunctorfwhere

fmap::(a->b)->fa->fb

This type is interesting - not like previous exmaples, like in EQ, where (==) :: (Eq a) => a -> a -> Bool. Here, f is NOT a concrete type, but a type constructor that takes one parameter.

18


Odds and ends in haskell folding i o and functors

Compare fmap to map:

fmap::(a->b)->fa->fb

map :: (a -> b) -> [a] -> [b]

So map is a lot like a functor! Here, map takes a function and a list of type a, and returns a list of type b.

In fact, can define map in terms of fmap:

instanceFunctor[]where

fmap=map

19


Odds and ends in haskell folding i o and functors

Notice what we wrote:

instanceFunctor[]where

fmap=map

We did NOT write “instance Functor [a] where…”, since f has to be a type constructor that takes one type.

Here, [a] is already a concrete type, while [] is a type constructor that takes one type and can produce many types, like [Int], [String], [[Int]], etc.

20


Odds and ends in haskell folding i o and functors

Another example:

instanceFunctorMaybewhere

fmapf(Justx)=Just(fx)

fmapfNothing=Nothing

Again, we did NOT write “instance Functor (Maybe m) where…”, since functor wants a type constructor.

Mentally replace the f’s with Maybe, so fmap acts like (a -> b) -> Maybe a -> Maybe b.

If we put (Maybe m), would have (a -> b) -> (Maybe m) a -> (Maybe m) b, which looks wrong.

21


Odds and ends in haskell folding i o and functors

Using it:

ghci>fmap(++"HEYGUYSIMINSIDETHE

JUST")(Just"Somethingserious.")

Just"Somethingserious.HEYGUYSIMINSIDETHEJUST"

ghci>fmap(++"HEYGUYSIMINSIDETHE

JUST")Nothing

Nothing

ghci>fmap(*2)(Just200)

Just400

ghci>fmap(*2)Nothing

Nothing

22


  • Login