" 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"> " 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">
Download presentation
Presentation is loading. Please wait.
Published byMelina Ramsey Modified over 8 years ago
1
© M. Winter COSC 4P41 – Functional Programming 11. 1 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
2
© M. Winter COSC 4P41 – Functional Programming 11. 2 myCustomer = Customer 1234 "Peter Pan" neverland Or alternatively: myCustomer = Customer { customerID = 1234, customerName = "Peter Pan", customerAddress= neverland }
3
© M. Winter COSC 4P41 – Functional Programming 11. 3 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
4
© M. Winter COSC 4P41 – Functional Programming 11. 4 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!
5
© M. Winter COSC 4P41 – Functional Programming 11. 5 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).
6
© M. Winter COSC 4P41 – Functional Programming 11. 6 Monad Transformers Properties for Monad Transformers t: 1.t :: (* -> *) -> * -> * 2.instance (Monad m) => Monad (t m) where... 3.instance MonadTrans t where lift :: Monad m => m a -> t m a 4.lift. return = return 5.lift (m >>= f) = lift m >>= (lift. f)
7
© M. Winter COSC 4P41 – Functional Programming 11. 7 import Control.Monad import Control.Monad.Trans newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } bindT :: (Monad m) => MaybeT m a -> (a -> MaybeT m b) -> MaybeT m b x `bindT` f = MaybeT (runMaybeT x >>= maybe (return Nothing) (runMaybeT. f)) returnT :: (Monad m) => a -> MaybeT m a returnT = MaybeT. return. return
8
© M. Winter COSC 4P41 – Functional Programming 11. 8 instance (Monad m) => Monad (MaybeT m) where return = returnT (>>=) = bindT instance MonadTrans MaybeT where lift m = MaybeT (m >>= (return. Just))
9
© M. Winter COSC 4P41 – Functional Programming 11. 9 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
10
© M. Winter COSC 4P41 – Functional Programming 11. 10 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] tree = Node "Moon" (Node "Ahmet" Empty Empty) (Node "Dweezil" (Node "Ahmet" Empty Empty) (Node "Moon" Empty Empty)) Moon Dweezil Ahmet Moon
11
© M. Winter COSC 4P41 – Functional Programming 11. 11 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) []
12
© M. Winter COSC 4P41 – Functional Programming 11. 12 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 …
13
© M. Winter COSC 4P41 – Functional Programming 11. 13 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))
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.