Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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