Вызов функций из государственной монады "Стек" в Haskell - PullRequest
0 голосов
/ 18 февраля 2019

У нас есть следующие типы, заданные задачей

newtype Trans state a = T {run :: state -> (a,state)}
type Stack a = Trans [Int] a

Я хочу написать функцию 1. нажать, чтобы поместить целое число в стек 2. всплывающее окно, чтобы вернуть и удалить самый высокий объект

Я попытался просмотреть монады состояний, чтобы понять их, и я понял концепцию, но не могу реализовать ее с заданной структурой типов.

1 Ответ

0 голосов
/ 18 февраля 2019

Pop и push довольно просты:

push :: Int -> Stack ()
push x = T { run = \st -> ((), x : st) }

pop :: Stack (Maybe Int)
pop = T
  { run = \st -> case st of
      (x : xs) -> (Just x, xs)
      _ -> (Nothing, st)
  }

pop - это тип Maybe Int, поскольку стек может быть пустым.В этом случае мы просто возвращаем Nothing.Но что мы можем с этим сделать?Ну, не много без Monad экземпляра.Давай сделаем один.Сначала нам нужно Functor и Applicative экземпляров:

instance Functor (Trans st) where
  fmap f (T r) = T
    { run = \st -> 
        let (result, state) = r st
        in (f result, state)
    }

instance Applicative (Trans st) where
  pure a = T { run = \st -> (a, st) }
  (<*>) (T fr) (T r) = T
    { run = \st ->
        let (result, state) = r st
            (f, nextState) = fr state
        in (f result, nextState)
    }

instance Monad (Trans a) where
  (>>=) (T r) f = T
    { run = \st ->
        let (result, state) = r st
        in run (f result) state
    }

Что это нам дает?Наконец, мы можем использовать наши pop и push функции:

simpleStack :: Stack Int
simpleStack = do
  push 10
  push 20
  push 30
  Just x <- pop
  return x

И мы можем проверить это следующим образом:

main :: IO ()
main = putStrLn $ show $ fst $ run simpleStack []
...