- 43 Views
- Uploaded on
- Presentation posted in: General

Grab Bag of Interesting Stuff

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 - - - - - - - - - - - - - - - - - - - - - - - - - -

Grab Bag of Interesting Stuff

- Type constructors are higher order since they take types as input and return types as output.
- Some type constructors (and also some class definitions) are even higher order, since they take type constructors as arguments.
- Haskell’s Kind system
- A Kind is haskell’s way of “typing” types
- Ordinary types have kind *
- Int :: *
- [ String ] :: *

- Type constructors have kind * -> *
- Tree :: * -> *
- [] :: * -> *
- (,) :: * -> * -> *

class Functor f where

fmap :: (a -> b) -> (f a -> f b)

- Note how the class Functorrequires a type constructor of kind * -> *as an argument.
- The method fmap abstracts the operation of applying a function on every parametric Argument.

a

a a

Type T a =

x

x x

(f x)

(f x) (f x)

fmap f

- Special syntax for built in type constructors
(->) :: * -> * -> *

[] :: * -> *

(,) :: * -> * -> *

(,,) :: * -> * -> * -> *

- Most class definitions have some implicit laws that all instances should obey. The laws for Functor are:
fmap id = id

fmap (f . g) = fmap f . fmap g

data Tree a = Leaf a

| Branch (Tree a) (Tree a)

instance Functor Tree where

fmap f (Leaf x) = Leaf (f x)

fmap f (Branch x y) =

Branch (fmap f x) (fmap f y)

instance Functor ((,) c) where

fmap f (x,y) = (x, f y)

instance Functor [] where

fmap f [] = []

fmap f (x:xs) = f x : fmap f xs

instance Functor Maybe where

fmap f Nothing = Nothing

fmap f (Just x) = Just (f x)

data Tree t a = Tip a

| Node (t (Tree t a))

t1 = Node [Tip 3, Tip 0]

Main> :t t1

t1 :: Tree [] Int

data Bin x = Two x x

t2 = Node (Two(Tip 5) (Tip 21))

Main> :t t2

t2 :: Tree Bin Int

- Tree is a binary type constructor
- It’s kind will be something like: ? -> ? -> *

- The first argument to Tree is itself a type constructor, the second is just an ordinary type.
- Tree :: (* -> *)-> * -> *

instance Functor (Tree2 Bin) where

fmap f (Tip x) = Tip(f x)

fmap f (Node (Two x y)) =

Node (Two (fmap f x) (fmap f y))

instance Functor (Tree2 []) where

fmap f (Tip x) = Tip(f x)

fmap f (Node xs) = Node (map (fmap f) xs)

instance Functor t => Functor (Tree2 t) where

fmap f (Tip x) = Tip(f x)

fmap f (Node xs) = Node (fmap (fmap f) xs)

Note m is a

type constructor

class Monad m where

(>>=) :: m a -> (a -> m b) -> m b

(>>) :: m a -> m b -> m b

return :: a -> m a

fail :: String -> m a

p >> q = p >>= \ _ -> q

fail s = error s

sequence :: Monad m => [m a] -> m [a]

sequence = foldrmcons (return [])

where mcons p q = do x <- p

xs <- q

return (x:xs)

sequence_ :: Monad m => [m a] -> m ()

sequence_ = foldr (>>) (return ())

mapM :: Monad m => (a -> m b) -> [a] -> m [b]

mapM f as = sequence (map f as)

mapM_ :: Monad m => (a -> m b) -> [a] -> m ()

mapM_ f as = sequence_ (map f as)

(=<<) :: Monad m => (a -> m b) -> m a -> m b

f =<< x = x >>= f

- The functions:
import System.IO

writeFile:: FilePath -> String -> IO ()

appendFile :: FilePath -> String -> IO ()

are used to read and write to files, but they incur quite a bit of overhead if they are used many times in a row. Instead we wish to open a file once, then make many actions on the file before we close it for a final time.

openFile :: FilePath -> IOMode -> IO Handle

hClose :: Handle -> IO ()

data IOMode = ReadMode | WriteMode | AppendMode

deriving (Eq, Ord, Ix, Bounded, Enum, Read, Show)

- A file mode tells how an open file will be used. Different modes support different operations.
- When in WriteMode
hPutChar :: Handle -> Char -> IO ()

hPutStr :: Handle -> String -> IO ()

hPutStrLn :: Handle -> String -> IO ()

hPrint :: Show a => Handle -> a -> IO ()

- When in ReadMode
hGetChar :: Handle -> IO Char

hGetLine :: Handle -> IO String

- Predefined standard Channels
stdin, stdout, stderr :: Handle

- Error Handling while doing IO
isEOFError :: IOError -> Bool

-- Test if the EOF error

ioError :: IOError -> IO a

-- Raise an IOError

catch :: IO a -> (IOError -> IO a) -> IO a

-- Handle an Error

- Other IO types of errors and their predicates.
isAlreadyExistsError, isDoesNotExistError,

isAlreadyInUseError, isFullError,

isEOFError, isIllegalOperation,

isPermissionError, isUserError,

- IOError is an abstract datatype
- NOT and algebraic datatype, defined with data like [ ] orTree

- Thus it does not admit pattern matching.
- Hence the use of all the IOError recognizing predicates.
- isAlreadyExistsError, isDoesNotExistError,
- isAlreadyInUseError, isFullError,
- isEOFError, isIllegalOperation,
- isPermissionError, isUserError

- This was a concious decision, made to allow easy extension of the kinds of IOErrors, as the system grew.

- Any action of type IO a may potentially cause an IO Error.
- The function
catch ::IO a -> (IOError -> IO a) -> IO a

can be used to gracefully handle such an error by providing a “fix”

getChar' :: IO Char

getChar' = catch getChar

(\ e -> return '\n')

getChar2 :: IO Char

getChar2 = catch getChar

(\ e -> if isEOFError e

then return '\n'

else ioError e) –- pass non EOF errors on

getLine' :: IO String

getLine' = catch getLine''

(\ e -> return

("Error: " ++ show e))

where getLine'' =

do { c <- getChar2

; if c == '\n'

then return ""

else do { l <- getLine'

; return (c:l)

}

}

getAndOpenFile :: String -> IOMode -> IO Handle

getAndOpenFile prompt mode =

do { putStr prompt

; name <- getLine

; catch (openFile name mode)

(\e -> do { putStrLn

("Cannot open: "++name)

; print e

; getAndOpenFile prompt mode

})

}

main =

do { fromHandle <- getAndOpenFile

"Copy from: " ReadMode

; toHandle <- getAndOpenFile

"Copy to: " WriteMode

; contents <- hGetContentsfromHandle

; hPutStrtoHandle contents

; hClosefromHandle

; hClosetoHandle

; putStr "Done\n"

}