Download Document

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
COSC 4P41 – Functional Programming
Further Features of Haskell
Records
data Customer = Customer {
customerID
:: Int,
customerName
:: String,
customerAddress
:: Address
}
The declaration defines the new data type Customer and its constructor
Customer :: Int -> String -> Address -> Customer.
In addition it also defines the following functions:
customerID
:: Customer -> Int
customerName
:: Customer -> String
customerAddress
:: Customer -> Address
© M. Winter
11.1
COSC 4P41 – Functional Programming
myCustomer = Customer 1234 "Peter Pan" neverland
Or alternatively:
myCustomer = Customer
customerID
=
customerName
=
customerAddress
=
}
© M. Winter
{
1234,
"Peter Pan",
neverland
11.2
COSC 4P41 – Functional Programming
Concurrency/Threads
Creating a thread:
forkIO :: IO () -> IO ThreadId
Example:
import Control.Concurrent (forkIO)
import qualified Data.ByteString.Lazy as L
import Codec.Compression.GZip (compress)
main = do
putStr "Enter a file to compress> "
name <- getLine
if null name
then return ()
else do
content <- L.readFile name
forkIO (compressFile name content)
main
where compressFile path = L.writeFile (path ++ ".gz") . compress
© M. Winter
11.3
COSC 4P41 – Functional Programming
Foreign Function Interface
import Foreign
import Foreign.C.Types
foreign import ccall "math.h sin"
c_sin :: CDouble -> CDouble
Points to consider:
• Side-effects in C function
– Use monad IO
• Thread safe code
– Multiple threads are extremely common in Hakell code!
© M. Winter
11.4
COSC 4P41 – Functional Programming
Monad Transformers
Motivation:
• We want to combine the monads IO and Maybe in order to be able to do
in/output as well as to catch errors. The result should be a new monad.
Bind for IO:
(>>=) :: IO a -> (a -> IO b) -> IO b
Bind for Maybe: (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
How do we get the new bind???
Solution:
• Create a monad transformer for Maybe that allows to wrap any monad m
around Maybe, i.e., m (Maybe a).
© M. Winter
11.5
COSC 4P41 – Functional Programming
import Control.Monad(liftM)
import Control.Monad.Trans
newtype MaybeT m a = MaybeT {
runMaybeT :: m (Maybe a)
}
bindMT :: (Monad m) =>
MaybeT m a -> (a -> MaybeT m b) -> MaybeT m b
x `bindMT` f = MaybeT $ do
unwrapped <- runMaybeT x
case unwrapped of
Nothing -> return Nothing
Just y -> runMaybeT (f y)
returnMT :: (Monad m) => a -> MaybeT m a
returnMT = MaybeT . return . return
© M. Winter
11.6
COSC 4P41 – Functional Programming
instance (Monad m) => Monad (MaybeT m) where
return = returnMT
(>>=) = bindMT
The class MonadTrans contains the function
lift :: (Monad m) => m a -> t m a
instance MonadTrans MaybeT where
lift m = MaybeT (Just `liftM` m)
where liftM :: Monad m => (a -> b) -> m a -> m b
liftM f m = do
x <- m
return (f x)
© M. Winter
11.7
COSC 4P41 – Functional Programming
Numbering Trees using State Monad
newtype StateT s m a = StateT {
runStateT :: s -> m (a,s)
}
type State s = StateT s Identity
evalState :: State s a -> s -> a
get :: (Monad m) => StateT s m s
get :: State s s
in the case m = Identity
put :: (Monad m) => s -> StateT s m ()
put :: s -> State s ()
in the case m = Identity
© M. Winter
11.8
COSC 4P41 – Functional Programming
import Data.List
import Control.Monad.Trans.State.Lazy
data Tree a = Empty | Node a (Tree a) (Tree a) deriving Show
type Table a = [a]
Moon
Ahmet
Dweezil
Ahmet
Moon
tree = Node "Moon"
(Node "Ahmet" Empty Empty)
(Node "Dweezil"
(Node "Ahmet" Empty Empty)
(Node "Moon" Empty Empty))
© M. Winter
11.9
COSC 4P41 – Functional Programming
numberTree :: Eq a => Tree a -> State (Table a) (Tree Int)
numberTree Empty
= return Empty
numberTree (Node x t1 t2) = do num <- numberNode x
nt1 <- numberTree t1
nt2 <- numberTree t2
return (Node num nt1 nt2)
numberNode :: Eq a => a -> State (Table a) Int
numberNode x = do table <- get
case (elemIndex x table) of
Nothing -> do put (table++[x])
return $ length table
Just n -> return n
runProg :: Eq a => Tree a => IO ()
runProg t = print $ evalState (numberTree t) []
© M. Winter
11.10
COSC 4P41 – Functional Programming
Using State Monad Transform
numberNode :: (Eq a, Show a) => a -> StateT (Table a) IO Int
numberNode x =
do table <- get
case (elemIndex x table) of
Nothing -> do put (table++[x])
lift $ putStrLn ("New value: " ++ show x)
return $ length table
Just n -> return n
numberTree :: (Eq a, Show a) =>
Tree a -> StateT (Table a) IO (Tree Int)
numberTree …
© M. Winter
11.11
COSC 4P41 – Functional Programming
evalStateT :: (Monad m) => StateT s m a -> s -> m a
runProg :: (Eq a, Show a) => Tree a => IO ()
runProg t = do t <- evalStateT (numberTree t) []
print t
Example session:
> runProg tree
New value: "Moon"
New value: "Ahmet"
New value: "Dweezil"
Node 0 (Node 1 Empty Empty) (Node 2 (Node 1 Empty Empty)
(Node 0 Empty Empty))
© M. Winter
11.12
Related documents