Доступ к счетчикам в State Monad haskell

у меня есть это

newtype State' s a = State' { runState' :: (s, Counts) -> (a, s, Counts) }

Теперь я хочу написать функцию

getCounts :: State' s a -> Counts

Есть ли способ добиться этого?


person dosmath    schedule 14.10.2014    source источник
comment
Я думаю, вы хотите что-то вроде этого: getCounts :: State' s Counts? (до того, как вы запустите вычисление своего состояния, вы не можете знать счетчики, поэтому вместо этого вы можете запросить счетчик из состояния?)   -  person Random Dev    schedule 14.10.2014
comment
Я отредактировал вопрос. Но как мне получить доступ к графам?   -  person dosmath    schedule 14.10.2014
comment
@CarstenKönig Я думаю, что это будет getCounts :: State' s Counts, если быть точнее.   -  person bheklilr    schedule 14.10.2014
comment
@bheklilr извините - да, конечно   -  person Random Dev    schedule 14.10.2014
comment
@CarstenKönig Counts — это моноид, состоящий из 4 разных целых чисел.   -  person dosmath    schedule 14.10.2014
comment
как насчет getCounts = State' (\ (s,c) -> (c,s,c)) ?   -  person Random Dev    schedule 14.10.2014
comment
Не будет ли State' s a ~ State (s, Counts) a где State от Control.Monad.State? Я бы предложил посмотреть, как get реализован для этой монады, чтобы получить некоторые идеи.   -  person bheklilr    schedule 14.10.2014
comment
@dosmath на самом деле не имеет значения, что такое Counts, если вы просто хотите получить его от государства - на самом деле это всего лишь еще один s (я думаю, это то, что bheklilr тоже хотел сказать)   -  person Random Dev    schedule 14.10.2014
comment
@CarstenKönig теперь функция getCounts возвращает количество состояний. Должен ли я теперь написать evalState', чтобы получить количество?   -  person dosmath    schedule 14.10.2014
comment
@dosmath - да, если вы дадите мне ваше определение evalState', я добавлю его к ответу - я думаю, это проще, чем делать это в режиме комментариев-чата   -  person Random Dev    schedule 14.10.2014


Ответы (1)


возможно, это то, что вы ищете:

getCounts :: State' s Counts
getCounts = State' (\ (s,c) -> (c,s,c))

затем вы можете использовать его внутри вычисления:

myStateComp = do
  -- whaever
  counts <- getCounts
  -- ...

и да, ты тоже можешь eval

предполагая, что ваш evalState' выглядит примерно так:

evalState' :: State' s a -> s -> Counts -> a
evalState' st initState initCounts = 
    let (a,_,_) = runState st (initState,initCounts)
    in a

то вы можете добраться до графов так:

evalState' getCounts initState initCount

конечно, это просто возвращает вам initCount - но без дальнейших вычислений я не вижу, что еще я мог бы ответить.

Реальный пример может быть примерно таким:

myComp = do
  -- ... do comp
  getCounts

а потом

evalState' myComp initState initCount

запустит любое вычисление внутри, а затем вернет последний счет

альтернатива

альтернатива, на которую намекал @bheklilr, использует

import Control.Monad.State

type State' s a = State (s, Counts) a

а также:

myStateComp = do
  -- whaever
  (state,counts) <- get
  -- ...

так что ваш getCounts на самом деле всего лишь fmap snd get

person Random Dev    schedule 14.10.2014
comment
Хорошо, но как мне это использовать, когда мне нужно написать функцию, которая возвращает (a, Counts). Если я правильно понимаю, теперь я могу получить доступ к Counts только в блоке do? - person dosmath; 14.10.2014
comment
вы используете свой eval с начальным состоянием - person Random Dev; 14.10.2014
comment
Спасибо за ваш ответ это помогло! - person dosmath; 14.10.2014