2012-11-22 8 views
0

Je suis novice dans le domaine des Monades et Haskell en général et j'essaie de comprendre comment retourner une valeur en les utilisant. Mon code ressemble à quelque chose comme ce qui suit:Renvoyer une valeur avec une monade d'état

foo :: A -> B 
foo a = do b <- fooC a (C 0) 
      -- want to return just (B "b") 

fooC :: A -> C -> State MyState B 
fooC a c = return (B "b") 

J'ai essayé d'utiliser snd (snd b), mais apparemment State MyState B n'est pas un tuple? Comment puis-je retourner la valeur désirée (B "b")?

Modifier: Prendre les conseils de Daniel en compte, la réécriture ressemble à ceci:

data MyState = MyState String 
data C = C Int 
foo :: String -> String 
-- want to return just "b" 
foo a = evalState (fooC a) (C 0) 

fooC :: String -> Int -> State MyState String 
fooC a c = return "b" 

Cela donne encore une erreur de compilation:

Couldn't match expected type `State s0 String' 
      with actual type `Int -> State MyState String' 
In the return type of a call of `fooC' 
Probable cause: `fooC' is applied to too few arguments 
In the first argument of `evalState', namely `(fooC a)' 
In the expression: evalState (fooC a) (C 0) 

Edit 2: fixe! La version finale se présente comme suit:

import Control.Monad.State 
data MyState = MyState String 
data C = C Int 
foo :: String -> String 
-- want to return just (B "b") 
foo a = evalState (fooC a (C 0)) (MyState "whatever") 

fooC :: String -> C -> State MyState String 
fooC a c = return "b" 

main = print(foo("test")) 
-- prints "b" 

Répondre

6

Qu'est-ce que vous avez besoin est

foo a = evalState (fooC a (C 0)) (MyState "whatever") 

Vous construisez l'action State MyState BfooC a (C 0), déballez pour obtenir une fonction, et d'appliquer cette fonction à un état initial. Puisque l'état n'est pas utilisé dans cet exemple, vous pouvez également utiliser ici undefined au lieu de MyState "whatever", mais en général, vous devez fournir un état initial significatif.

State MyState B n'est pas un tuple, il est isomorphe à une fonction

MyState -> (B, MyState) 

, mais cette fonction est enveloppée dans une newtype (détails varient selon le package de bibliothèque transformateur monade et version), pour ainsi accéder au résultat de cette fonction appliquée à un état initial, vous avez besoin d'une fonction de déballage. Pour State, il y a

runState :: State s r -> (s -> (r,s)) 

qui vous donne la fonction renvoyant la paire,

evalState :: State s r -> (s -> r) 

qui vous donne la fonction composée de fst, de sorte que l'état final est mis au rebut, et

execState :: State s r -> (s -> s) 

qui compose la fonction avec snd, de sorte que seul l'état final est renvoyé.

+0

Cela ne semblait pas fonctionner. Voir la modification dans mon message. –

+0

Oups, désolé parse échec de ma part. Actualisé. –

+0

A travaillé! Merci Daniel! –

Questions connexes