Links und Funktionen
Sprachumschaltung

Navigationspfad
Sie sind hier: Startseite / Lehre / SS 2018 / Programmierung und Modellierung / ProMo Material / Code 20.06.18


Inhaltsbereich

Code 20.06.18

Zustands-Monade zu Fuss implementiert

Haskell source code icon welt.hs — Haskell source code, 2 KB (2815 bytes)

Dateiinhalt

{-# LANGUAGE InstanceSigs #-}
-- Code aus Vorlesung "Programmierung und Modellierung", Sommersemester 2018
-- Steffen Jost, LMU München

-- Analogie: MyIO als Zustandsmonade

import Prelude

data Welt = Welt { zeit :: Int, wetter :: String }
  deriving Show

type MyIO a = Welt -> (a,Welt)

komposition :: MyIO a -> ( a -> MyIO b) -> MyIO b
-- komposition ::
--   (Welt -> (a,Welt))
--   -> ( a -> Welt -> (b,Welt))
--   -> Welt
--   -> (b, Welt)
komposition ersteAkt zweitAkt welt1 =
--   let (xa,welt2) = ersteAkt welt1
--       (yb,welt3) = zweitAkt xa welt2
--   in (yb,welt3)
  let (xa,welt2) = ersteAkt welt1
  in zweitAkt xa welt2

nacheinander :: MyIO a -> MyIO b -> MyIO b
nacheinander ersteAkt zweitAkt = ersteAkt `komposition` (\_ -> zweitAkt)

tick :: MyIO Int
-- tick :: Welt -> (Int,Welt)
tick welt = (zeit welt, welt { zeit = 1 + zeit welt} )

tauscheWetter :: String -> MyIO String
tauscheWetter s welt = ( wetter welt  , welt { wetter = s } )

sonne :: MyIO ()
sonne welt = ( (), welt { wetter = "sonnig" } )

machWetter :: String -> MyIO ()
machWetter w welt = ( (), welt { wetter = w } )

-- Test
startWelt :: Welt
startWelt = Welt { wetter="kalt", zeit=0 }

test1 :: MyIO String
test1 =
  tick  `nacheinander`
  tick  `nacheinander`
  sonne `nacheinander`
  tick  `nacheinander`
  tauscheWetter "regen" `komposition`
  tauscheWetter

newtype Zustand a = Zu (Welt -> (a,Welt))

noZu :: Zustand a -> (Welt -> (a,Welt))
noZu (Zu act) = act

instance Monad Zustand where
  return :: a -> Zustand a -- Zu (Welt -> (a,Welt))
  return x = Zu $ \w -> (x,w)

  act1 >>= act2 = Zu $ \w1 ->
                    let (a, w2) = noZu act1 w1
                    in noZu (act2 a) w2
{-
instance Functor Zustand where
  fmap f mx = mx >>= (\x -> return $ f x)
-}
instance Functor Zustand where
  fmap f mx = -- f  ::   a -> b
              -- mx :: Zustand a
              -- <ergebnis> :: Zustand b
              Zu $ \w1 ->
                  let (xa,w2) = noZu mx w1
                  in (f xa,w2)
{-
instance Applicative Zustand where
  pure = return
  mf <*> mx = mf >>= (\f -> mx >>= (\x -> return $ f x) )
-}
instance Applicative Zustand where
  pure x = Zu $ \w -> (x,w)
  mf <*> mx = Zu $ \w1 ->
              let (f,w2) = noZu mf w1
                  (x,w3) = noZu mx w2
              in (f x, w3)


swapWetter :: String -> Zustand String
swapWetter wetterneu = Zu $ \w1 -> (wetter w1, w1 {wetter=wetterneu})

swapInt :: Int -> Zustand Int
swapInt i = Zu $ \(Welt z w) -> (z, Welt i w)

incInt :: Zustand ()
incInt = do
  i <- swapInt 0
  swapInt $ i+1
  return ()

testNeu :: Zustand ()
testNeu = do
  incInt
  incInt
  incInt
  incInt
  x <- swapInt 999
  let xshown = "Zeit war: " ++ show x
  altWetter <- swapWetter xshown
  incInt


runTest :: ((), Welt)
runTest = noZu testNeu (Welt 0 "regen")


Artikelaktionen


Funktionsleiste