Я пытаюсь придумать реализацию State Monad, основанную на примерах композиции функций.Вот что я придумал:
Сначала выведем понятие Монады:
data Maybe' a = Nothing' | Just' a deriving Show
sqrt' :: (Floating a, Ord a) => a -> Maybe' a
sqrt' x = if x < 0 then Nothing' else Just' (sqrt x)
inv' :: (Floating a, Ord a) => a -> Maybe' a
inv' x = if x == 0 then Nothing' else Just' (1/x)
log' :: (Floating a, Ord a) => a -> Maybe' a
log' x = if x == 0 then Nothing' else Just' (log x)
Мы можем иметь функцию, которая составляет следующие функции:
sqrtInvLog' :: (Floating a, Ord a) => a -> Maybe' a
sqrtInvLog' x = case (sqrt' x) of
Nothing' -> Nothing'
(Just' y) -> case (inv' y) of
Nothing' -> Nothing'
(Just' z) -> log' z
Это можно упростить, выделив оператор case и приложение-функцию:
fMaybe' :: (Maybe' a) -> (a -> Maybe' b) -> Maybe' b
fMaybe' Nothing' _ = Nothing'
fMaybe' (Just' x) f = f x
-- Applying fMaybe' =>
sqrtInvLog'' :: (Floating a, Ord a) => a -> Maybe' a
sqrtInvLog'' x = (sqrt' x) `fMaybe'` (inv') `fMaybe'` (log')`
Теперь мы можем обобщить концепцию на любой тип, а не просто Maybe, определив Monad =>
class Monad' m where
bind' :: m a -> (a -> m b) -> m b
return' :: a -> m a
instance Monad' Maybe' where
bind' Nothing' _ = Nothing'
bind' (Just' x) f = f x
return' x = Just' x
Используя реализацию Monad, sqrtInvLog 'можно записать в виде:
sqrtInvLog''' :: (Floating a, Ord a) => a -> Maybe' a
sqrtInvLog''' x = (sqrt' x) \bind'` (inv') `bind'` (log')`
Пытаясь применить концепцию для поддержания состояния, я определил что-то, как показано ниже:
data St a s = St (a,s) deriving Show
sqrtLogInvSt' :: (Floating a, Ord a) => St a a -> St (Maybe' a) a
sqrtLogInvSt' (St (x,s)) = case (sqrt' x) of
Nothing' -> St (Nothing', s)
(Just' y) -> case (log' y) of
Nothing' -> St (Nothing', s+y)
(Just' z) -> St (inv' z, s+y+z)
Невозможно определить монаду, используя приведенное выше определение, так как привязка должна быть определена как получение в единственном типе "ma".
Вторая попытка, основанная на определении Хаскеллом State Monad:
newtype State s a = State { runState :: s -> (a, s) }
Первая попытка определить функцию, которая построена с использованием составных функций и поддерживает состояние:
fex1 :: Int->State Int Int
fex1 x = State { runState = \s->(r,(s+r)) } where r = x `mod` 2`
fex2 :: Int->State Int Int
fex2 x = State { runState = \s-> (r,s+r)} where r = x * 5
Составная функция:
fex3 x = (runState (fex2 y)) st where (st, y) = (runState (fex1 x)) 0
Но определение newtype State s a = State { runState :: s -> (a, s) }
не соответствуетобразецm a -> (a -> m b) -> m b
of bind
Попытка может быть предпринята следующим образом:
instance Monad' (State s) where
bind' st f = undefined
return' x = State { runState = \s -> (x,s) }
bind 'не определено выше, потому что я не знал, как я это реализую.
Я мог бы понять, почему монады полезны, и применить его в первом примере (возможно), но, похоже, не могу применить его к государству.Будет полезно понять, как я мог получить Государственный Моанд, используя понятия, определенные выше.
Обратите внимание, что я задавал подобный вопрос ранее: Haskell - Невозможно определить функцию, подобную Монаде, используя Монаду.как определение , но я расширил здесь и добавил больше деталей.