Sur EDIT3, il y a un seul fichier avec le code presque complet.
https://github.com/agutie58/landOfLispInHaskell/blob/main/exampleLoLTextGameHaskell.hs
Et sur EDIT2 un exemple du jeu réel.
[ORIGINAL] J'ai une fonction "run" qui est basée sur un domaine, et une liste d'événements, si tous les événements sont traités, elle écoute les nouveaux événements, et s'il s'agit d'événements, elle en traite plusieurs. La majorité des événements modifie le Domaine :
data Domain = Domain (String, World) deriving (Show)
data World = World {loc :: String, descSites :: [(Key,String)], mapSites :: [(Key, [Lloc])], objects:: [Key], siteObjects::[(Key,String)]} deriving (Show)
run :: Domain -> [Event] -> IO ()
run dm [] = do
events <- uiUpdate dm
run dm events
run _ (EventExit:_) =
return ()
run dm (e:es) =
run (dmUpdate dm e) es
La partie sur laquelle je veux me concentrer est : "run (dmUpdate dm e) es". Le "dmUpdate dm e" renvoie un type Domain.
Un exemple de cette fonction dmUpdate qui fonctionne bien est (où look :: World -> Domain ; walk :: String -> World -> Domain; etc.) :
dmUpdate :: Domain -> Event -> Domain
dmUpdate (Domain v) (EventLook) = look (snd v)
dmUpdate (Domain v) (EventWalk direction) = walk direction (snd v)
dmUpdate dm _ _ = dm
Je veux rendre (imprimer sur console) le résultat d'un nouveau domaine. Par exemple:
dmUpdate (Domain v) (EventLook) = do let newDomain = look (snd v)
putStr (fst newDomain)
newDomain
Mais cela ne fonctionne pas. J'essaie de calculer un nouvel état du monde, puis IO, puis j'essaie de renvoyer le newDomain en tant que paramètre.
J'ai pensé passer une fonction comme ça :
run dm (e:es) =
run (dmUpdate dm e renderMsg) es
where renderMsg txt = (putStr txt) >> (hFlush stdout)
.. Pour faire quelque chose comme :
-- dmUpdate :: dmUpdate :: Domain -> Event -> (String -> IO ()) -> IO () -> Domain
dmUpdate (Domain v) (EventLook) (renderMsg) = let newDomain = look (snd v)
renderMsg (fst newDomain)
Mais ne fonctionne pas.
Des idées !? Merci d'avance!
EDIT1 : j'ai aussi essayé :
dmUpdate :: Domain -> Event -> IO Domain
dmUpdate (Domain v) (EventLook) = do let newDomain = look (snd v)
putStr (fst newDomain)
newDomain
dmUpdate dm _ _ = () dm
... mais j'ai ce message :
[2 of 2] Compiling Main ( textGameMain.hs, interpreted )
textGameMain.hs:25:1: error:
Equations for ‘dmUpdate’ have different numbers of arguments
textGameMain.hs:(25,1)-(27,47)
textGameMain.hs:33:1-23
|
25 | dmUpdate (Domain v) (EventLook) = do let newDomain = look (snd v)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
textGameMain.hs:70:8: error:
• Couldn't match expected type ‘Domain’
with actual type ‘IO Domain’
• In the first argument of ‘run’, namely ‘(dmUpdate dm e)’
In the expression: run (dmUpdate dm e) es
In an equation for ‘run’: run dm (e : es) = run (dmUpdate dm e) es
|
70 | run (dmUpdate dm e ) es
Alors, j'ai essayé de changer de run :
run dm (e:es) =
run () (dmUpdate dm e ) es
Mais je n'ai pas réussi à le faire fonctionner.. :S
EDIT2 : Donc, mon code fait ça (il est basé sur "Land of Lisp", et c'est une adaptation à Haskell) :
*Main> main WORLD> regardez vous êtes dans le salon. un sorcier ronfle bruyamment sur le canapé. Il y a une porte vers l'ouest à partir d'ici. Il y a une échelle qui monte à l'étage d'ici. Vous voyez un whisky par terre. Vous voyez un seau sur le sol.
MONDE> marche vers l'ouest MONDE> regarde, tu es dans un beau jardin. il y a un puits devant vous. Il y a une porte qui va vers l'est à partir d'ici. Vous voyez une grenouille sur le sol. Vous voyez une chaîne sur le sol.
EDIT3 : (code complet - en fait j'ai regroupé deux fichiers en un seul pour plus de simplicité... il existe une autre manière d'ajouter un fichier !?) https://github.com/agutie58/landOfLispInHaskell/blob/main/exampleLoLTextGameHaskell. hs
ghci exampleLoLTextGameHaskell.hs main
(.. et puis, quelque chose à EDIT2 ..)
Votre code est loin d'être complet, contient beaucoup de - pour votre question - des parties inutiles. J'ai copié votre code, simplifié un peu et fait quelques devinettes. Voici ma version "fixe".
module Tmp where
import Text.Read (readMaybe)
{-| Be clear about your types. Introducing type alisases helps others read your code.
I simply guessed that the string-part of the Domain is the UI state -}
type UIState = String
data Domain = Domain (UIState,World) deriving Show
data World = World {loc:: Int} deriving Show
-- | I Have only implemented two directions, so that this example is easy to work with.
data Dir = L | R deriving (Read, Show)
{- | These were the event types that you had in your code. I elaborated them a little.
By using the "deriving (Read)" we get a low-code input mechanism, but you should probalbly write
your own input parser
-}
data Event = EventExit | EventWalk Dir| EventLook deriving (Read)
-- | The run-loop now has TWO steps. Render UI and get new events. Process events. Finally recurse.
run :: Domain -> [Event] -> IO ()
run dm [] = uiUpdate dm >> getAction >>= run dm
run _ (EventExit:_) = return ()
run dm (e:es) = run (dmUpdate dm e) es
{-| Update the domain when a single event acts on it -}
dmUpdate :: Domain -> Event -> Domain
dmUpdate (Domain v) (EventLook) = look (snd v)
dmUpdate (Domain v) (EventWalk direction) = walk direction (snd v)
dmUpdate dm _ = dm
look w = Domain ("You are at coordinate " ++ (show .loc $ w), w)
walk L w@World{loc=l}= Domain ("You went left", w{loc=l-1})
walk R w@World{loc=l} = Domain ("You went right", w{loc=l+1})
{-| Present the "output" that the domain holds for us -}
uiUpdate :: Domain -> IO ()
uiUpdate dm = do
let Domain (usState,s) = dm
putStrLn usState
{-| Ask user for input. Only a single event is collected. -}
getAction :: IO [Event]
getAction = do
putStrLn "What do you want to do? Choose between EventExit | EventWalk R | EventWalk L | EventLook"
act <- readMaybe <$> getLine
case act of
Nothing -> putStrLn "Not a valid action" >> getAction
Just evt -> pure [evt]
main :: IO ()
main = run (Domain ("",World 0)) [EventLook]
Enfin, vous voudrez peut-être examiner StateT afin de pouvoir faire abstraction de l'objet Domain qui est transmis tout le temps. Mais cela sort du cadre de cette question, je suppose.
Cet article est collecté sur Internet, veuillez indiquer la source lors de la réimpression.
En cas d'infraction, veuillez [email protected] Supprimer.
laisse moi dire quelques mots