When you define a class in a object-oriented language it usually sets the default values for the member variables. Is there any mechanism in Haskell to do the same thing in record types? And a follow up question: If we don't know from the very start all the values for a data constructor but we obtain them from IO interaction can we build the type using something like the builder pattern from OOP?
Thanks in advance
A common idiom is to define a default value.
data A = A { foo :: Int , bar :: String }
defaultA :: A
defaultA = A{foo = 0, bar = ""}
This can be then (purely) "updated" later on with real values.
doSomething :: Bool -> A
doSomething True = defaultA{foo = 32}
doSomething False = defaultA{bar = "hello!"}
Pseudocode example:
data Options = O{ textColor :: Bool, textSize :: Int, ... }
defaultOptions :: Options
defaultOptions = O{...}
doStuff :: Options -> IO ()
doStuff opt = ...
main :: IO ()
main = do
...
-- B&W, but use default text size
doStuff defaultOptions{ color = False }
If there are no sensible default values, you can wrap the field values in Maybe.
If you feel adventurous, you can even use a more advanced approach to statically separate "intermediate" options values, which can lack a few fields, from "finalized" ones, which must have all the fields. (I'd not recommend this to Haskell beginners, though.)
Is there any mechanism in Haskell to do the same thing in record types?
What you can do is hide the constructor, and provide a function as constructor instead.
Say for instance we have a list we want to update, together with a revision number, then we can define it as:
data RevisionList a = RevisionList { theList :: [a],
revision :: Int }
deriving Show
Now we can define a function that initializes the BuildList with an initial list:
revisionList :: [a] -> RevisionList a
revisionList xs = RevisionList { theList = xs, revision=0 }
and by hiding the constructor in the module export, we thus hide the possibility to initialize it with another revision than revision 0. So the module could look like:
module Foo(RevisionList(), revisionList)
data RevisionList a = RevisionList { theList :: [a],
revision :: Int }
revisionList :: [a] -> RevisionList a
revisionList xs = RevisionList { theList = xs, revision=0 }
something like the builder pattern from OOP?
We can for instance use a State monad for that. For instance:
module Foo(RevisionList(), revisionList,
increvision, RevisionListBuilder, prefixList)
import Control.Monad.State.Lazy
type RevisionListBuilder a = State (RevisionList a)
increvision :: RevisionListBuilder a ()
increvision = do
rl <- get
put (rl { revision = 1 + revision rl})
prefixList :: a -> RevisionListBuilder a ()
prefixList x = do
rl <- get
put (rl { theList = x : theList rl })
increvision
So we get the RevisionList thus far, perform updates, put the new result back, and increment the revision number.
So now another module can import our Foo, and use the builder like:
some_building :: RevisionListBuilder Int ()
some_building = do
prefixList 4
prefixList 1
and now we can "make" a RevisionList at revision 2 with as final list [1,4,2,5] with:
import Control.Monad.State.Lazy(execState)
some_rev_list :: RevisionList Int
some_rev_list = execState some_building (revisionList [2,5])
So it would look approximately like:
Foo.hs:
module Foo(RevisionList(), revisionList,
increvision, RevisionListBuilder, prefixList)
data RevisionList a = RevisionList { theList :: [a],
revision :: Int }
deriving Show
type RevisionListBuilder a = State (RevisionList a)
revisionList :: [a] -> RevisionList a
revisionList xs = RevisionList { theList = xs, revision=0 }
increvision :: RevisionListBuilder a ()
increvision = do
rl <- get
put (rl { revision = 1 + revision rl})
prefixList :: a -> RevisionListBuilder a ()
prefixList x = do
rl <- get
put (rl { theList = x : theList rl })
increvision
Bar.hs:
import Foo
import Control.Monad.State.Lazy(execState)
some_building :: RevisionListBuilder Int ()
some_building = do
prefixList 4
prefixList 1
some_rev_list :: RevisionList Int
some_rev_list = execState some_building (revisionList [2,5])
So now we have constructed a some_rev_list with the "building" of some_building:
Foo Bar> some_rev_list
RevisionList {theList = [1,4,2,5], revision = 2}
There's already good answers here, so this answer is only meant as a supplement to the fine answers from chi and Willem Van Onsem.
In mainstream object-oriented languages like Java and C#, it's not that a default object is uninitialised; rather, a default object is normally initialised with default values for their types, and it just happens that for reference types, the default is a null reference.
Haskell doesn't have null references, so records can't be initialised with nulls. The most direct translation of objects would be records where every single constituent element is a Maybe. That's not particularly useful, however, but it highlights how hard it is to protect invariants in OOP.
The Builder pattern doesn't solve that problem at all. Any Builder has to start with an initial Builder object, and that object is going to have to have default values as well.
For more details, and lots of examples, I wrote an article series about this. The article series specifically focuses on the Test Data Builder pattern, but you should be able to see how it generalises to the Fluent Builder pattern in general.
Related
I have a state where it contains different values and I want to use the same function to update different values in the state. But I am unable to do so because of the following error.
Error Received:
warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: currentRegister -> ...
|
559 | currentRegister -> modify $ \st->st{ currentRegister = nextAddr}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
data St = St
{ cotxt :: [Cxt]
, currentLabel :: Int
, currentLogicLabel :: Int
, currentIfLabel :: Int
, currentWhileLabel :: Int
, currentRegister :: Int
}
getcurrStateValue :: (St -> Int) -> Compile Int
getcurrStateValue x = do
current <- gets x
let nextAddr = current + 1
case x of
currentLabel -> modify $ \st->st{ currentLabel = nextAddr}
currentRegister -> modify $ \st->st{ currentRegister = nextAddr}
currentLogicLabel -> modify $ \st->st{ currentLogicLabel = nextAddr}
currentIfLabel -> modify $ \st->st{ currentIfLabel = nextAddr}
currentWhileLabel -> modify $ \st->st{ currentWhileLabel = nextAddr}
return current
func1::
..
current <- getcurrStateValue currentRegister
..
func2::
anothercurrent <- getcurrStateValue currentLogicLabel ```
As commenters have pointed out, in this case expression, you’re trying to compare the parameter x with the getter functions from the St type.
case x of
currentLabel -> modify $ \ st -> st { currentLabel = nextAddr }
currentRegister -> modify $ \ st -> st { currentRegister = nextAddr }
-- …
Unfortunately, functions cannot be compared; only data constructors and numeric literals (Num + Eq) can appear in basic patterns. What your code actually does is match x against anything, and bind it to a new local variable currentLabel, and then all the subsequent case branches (currentRegister and so on) are redundant, as the warning tells you.
It’s just as if you had written this, with distinct variable names:
case x of
a -> modify $ \ st -> st { currentLabel = nextAddr }
b -> modify $ \ st -> st { currentRegister = nextAddr }
-- …
A simple solution here is to add a new enumeration type indicating which field you want to modify, and pattern-match on that:
data Field
= CurrentLabel
| CurrentLogicLabel
| CurrentIfLabel
| CurrentWhileLabel
| CurrentRegister
getCurrStateValue :: Field -> Compile Int
getCurrStateValue field = case field of
CurrentLabel -> do
current <- gets currentLabel
modify $ \ st -> st { currentLabel = current + 1 }
pure current
CurrentRegister -> do
current <- gets currentRegister
modify $ \ st -> st { currentRegister = current + 1 }
pure current
CurrentLogicLabel -> do
current <- gets currentLogicLabel
modify $ \ st -> st { currentLogicLabel = current + 1 }
pure current
CurrentIfLabel -> do
current <- gets currentIfLabel
modify $ \ st -> st { currentIfLabel = current + 1 }
pure current
CurrentWhileLabel -> do
current <- gets currentWhileLabel
modify $ \ st -> st { currentWhileLabel = current + 1 }
pure current
As you can see, though, this is quite repetitive! A better solution is to pass both a getter and a setter function (whereas currently you’re only passing the getter):
getCurrStateValue
:: (St -> Int)
-> (St -> Int -> St)
-> Compile Int
getCurrStateValue getField setField = do
current <- gets getField
modify $ \ st -> setField st $ current + 1
pure current
Of course, now this has moved the repetitiveness to the call site, since you must pass both functions, and they must refer to the same field:
current <- getCurrStateValue
currentRegister
(\ st x -> st { currentRegister = x })
So an improvement would be to package up these invocations into helper functions for each field:
getCurrRegister = getCurrStateValue
currentRegister
(\ st x -> st { currentRegister = x })
getCurrLogicLabel = getCurrStateValue
currentLogicLabel
(\ st x -> st { currentLogicLabel = x })
I think this is a good place to stop: the repetition is abstracted away without too much heavy machinery.
However, this can be abstracted further. The combination of a getter and setter for the same field is very useful, and it would be nice to reuse it with other functions besides getCurrStateValue.
A getter+setter pair can be packaged up into a lens (or more generally an “optic”), which is a first-class accessor that can be composed with other lenses. While there are many lens libraries like lens (big and complete) and microlens (small and simple) containing functions for working with lenses, you don’t actually need any dependencies to define a lens; it’s just a function with a type like this:
(Functor f) => (a -> f b) -> s -> f t
Or, slightly simplified:
(Functor f) => (a -> f a) -> s -> f s
How this works is beyond the scope of this answer, but what it means is an accessor for a field of type a within a structure of type s. In your case, a is always Int and s is St. Here’s a helper function for defining a lens from a getter and setter:
lens
:: Functor f
=> (s -> a) -- get ‘a’ out of ‘s’
-> (s -> a -> s) -- put ‘a’ into ‘s’
-> (a -> f a) -> s -> f s -- lens
lens getter setter
= \ f s -> fmap (setter s) (f (getter s))
Using this, you can define lenses for your fields:
currentRegisterL, currentLogicLabelL -- …
:: (Functor f) => (Int -> f Int) -> St -> f St
currentRegisterL = lens
currentRegister
(\ st x -> st { currentRegister = x })
currentLogicLabelL = lens
currentLogicLabel
(\ st x -> st { currentLogicLabel = x })
-- …
And then use them with functions and types from lens, such as view to use the getter part and set to use the setter. To take a lens as a function parameter, you need the RankNTypes extension, which allows passing polymorphic functions like lenses as arguments to other functions.
{-# LANGUAGE RankNTypes #-}
import Control.Lens (Lens', set, view)
getCurrStateValue :: Lens' St Int -> Compile Int
getCurrStateValue field = do
current <- gets $ view field
modify $ set field $ current + 1
pure current
Most of the time, when using lenses, people don’t write their own by hand, unless they specifically want to avoid a dependency on a lens package. Instead, it’s common to automate this by deriving lenses for a data type with Template Haskell:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens.TH (makeLenses)
data St = St
{ _cotxt :: [Cxt]
, _currentLabel :: Int
, _currentLogicLabel :: Int
, _currentIfLabel :: Int
, _currentWhileLabel :: Int
, _currentRegister :: Int
}
makeLenses ''St
The convention is that the getters and record accessors are prefixed with an underscore, like _currentLabel, and the lenses derived from them have no prefix, like currentLabel. You can still use the accessor functions directly, but when you need to abstract over field access, you can use view, set, over, and other such functions.
Pattern matching only works with data constructors; it can't check for equality of values. (Patterns like x:xs, [x,y], and (x,y) are treated constructor matches.) In particular, there is no other general way to handle coproduct types like data Foo = Bar | Baz. (Aside from using Eq, Ord, etc.)
What you probably need here is a lens.
I am new to Haskell and need help. I am trying to build a new data type that has to be somehow unique, so I decided to use UUID as a unique identifier:
data MyType = MyType {
uuid :: UUID,
elements :: AnotherType
}
in this way, I can do following:
instance Eq MyType where
x == y = uuid x == uuid y
x /= y = not (x == y)
The problem is that all known (to me) UUID generators produce IO UUID, but I need to use it in a pure code as mentioned above. Could you please suggest if there is any way to extract UUID out of IO UUID, or maybe be there is a better way to do what I need in Haskell? Thanks.
UPDATE
Thanks for all the great suggestions and the code example. From what is posted here I can say you cannot break a referential transparency, but there are smart ways how to solve the problem without breaking it and, probably the most optimal one, is listed in the answer below.
There is also one alternative approach that I was able to explore myself based on provided recommendations with the usage of State Monad:
type M = State StdGen
type AnotherType = String
data MyType = MyType {
uuid :: UUID,
elements :: AnotherType
} deriving (Show)
mytype :: AnotherType -> M MyType
mytype x = do
gen <- get
let (val, gen') = random gen
put gen'
return $ MyType val x
main :: IO ()
main = do
state <- getStdGen
let (result, newState) = runState (mytype "Foo") state
putStrLn $ show result
let (result', newState') = runState (mytype "Bar") newState
setStdGen newState'
putStrLn $ show result'
Not sure if it is the most elegant implementation, but it works.
If you're looking at the functions in the uuid package, then UUID has a Random instance. This means that it's possible to generate a sequence of random UUIDs in pure code using standard functions from System.Random using a seed:
import System.Random
import Data.UUID
someUUIDs :: [UUID]
someUUIDs =
let seed = 123
g0 = mkStdGen seed -- RNG from seed
(u1, g1) = random g0
(u2, g2) = random g1
(u3, g3) = random g2
in [u1,u2,u3]
Note that someUUIDs creates the same three "unique" UUIDs every time it's called because the seed is hard-coded.
As with all pure Haskell code, unless you cheat (using unsafe functions), you can't expect to generate a sequence of actually unique UUIDs without explicitly passing some state (in this case, a StdGen RNG) between calls to random.
The usual solution to avoid the ugly boilerplate of passing the generator around is to run at least part of your code within a monad that can maintain the needed state. Some people like to use the MonadRandom package, though you can also use the regular State monad with a StdGen somewhere in the state. The main advantages of MonadRandom over State is that you get some dedicated syntax (getRandom) and can create a monad stack that includes both RandomT and StateT so you can separate your RNG state from the rest of your application state.
Using MonadRandom, you might write an application like:
import Control.Monad.Random.Strict
import System.Random
import Data.UUID
-- monad for the application
type M = Rand StdGen
-- get a generator and run the application in "M"
main :: IO ()
main = do
g <- getStdGen -- get a timestamp-seeded generator
let log = evalRand app g -- run the (pure) application in the monad
putStr log
-- the "pure" application, running in monad "M"
app :: M String
app = do
foo <- myType "foo"
bar <- myType "bar"
-- do some processing
return $ unlines ["Results:", show foo, show bar]
type AnotherType = String
data MyType = MyType {
uuid :: UUID,
elements :: AnotherType
} deriving (Show)
-- smart constructor for MyType with unique UUID
myType :: AnotherType -> M MyType
myType x = MyType <$> getRandom <*> pure x
Note that substantial parts of the application will need to be written in monadic syntax and run in the application M monad. This isn't a big restriction -- most non-trivial applications are going to be written in some monad.
Let's say, I have the following types:
type LinkID = Int
data Link = Link {
lid :: LinkID,
llength :: Int
}
data Snap = Snap {
slid :: LinkID,
slength :: Int
}
Now, I want to write a pipes based function which does this:
getSnaps :: LinkID -> [Link] -> [Snap] -> [(LinkID, [Snap])]
getSnaps l lks snp = map (\x -> (lid x, filter (\y -> lid x == slid y) snp)) a
where a = filter (\x -> lid x > l) lks
Assumming that I already have Producers of Link and Snap, how can I implement the above getSnaps function in the Pipes world from these two Producers:
psnap :: Producer Snap IO ()
psnap = undefined
plink :: Producer Link IO ()
plink = undefined
The actual types of psnap and plink are more involved (created out by using attoparsec-pipes), but I would like to know how to implement the functionality of getSnaps from psnap and plink. Is there a proper way to solve this type of problem ?
The solution I came up with is pretty similar to your code. I just replaced map with Pipes.Prelude.map and one of the filters with Pipes.Prelude.filter:
import Pipes
import qualified Pipes.Prelude as Pipes
type LinkID = Int
data Link = Link
{ lid :: LinkID
, llength :: Int
}
data Snap = Snap
{ slid :: LinkID
, slength :: Int
}
getSnaps
:: Monad m
=> LinkID
-> Producer Link m ()
-> Producer Snap m ()
-> Producer (LinkID, [Snap]) m ()
getSnaps l lks snp = do
snp' <- lift (Pipes.toListM snp) -- Cache `snp` into the list `snp'`
lks >-> Pipes.filter (\x -> lid x > l)
>-> Pipes.map (\x -> (lid x, filter (\y -> lid x == slid y) snp'))
Note that there is one non-trivial part, which is that the above solution strictly loads the snp Producer's contents into the list snp'. The reason for this is that we have to use the contents of the list repeatedly, so we need to cache the entire list in memory for repeated usage.
I want have some piece of code where I want to call a function foo with different implementations of foo residing in different modules.
Like
foo :: String -> IO[String]
module A:
foo :: String -> IO[String]
foo x = whatever
module B:
foo :: String -> IO[String]
foo x = whatever (different)
and then call the appropriate function based on some parameter. I could do with qualified imports:
import qualified ModuleA as A
import qualified ModuleB as B
bar :: String -> String -> IO[String]
bar moduleToChoose x = case moduleToChoose of
"A" -> A.foo x
"B" -> B.foo x
_ -> Uh oh...
This, however basically screams "There is a so much more elegant™ solution to this but you just don't get it!" Is there a better solution?
Modules aren't first class in Haskell, and so there is no way to use them directly as parameters. In any case, an improvement on your solution would be using a sum type to encode the distinction in a richer and safer way. That can feel pretty natural given meaningful names for modules, types and values (i.e., names that actually reflect what you are trying to do):
import qualified Formatting.Mimsy as Mimsy
import qualified Formatting.Slithy as Slithy
data FormattingStyle = Mimsy | Slithy
foo :: FormattingStyle -> String -> IO [String]
foo style x = case style of
Mimsy -> Mimsy.foo x
Slithy -> Slithy.foo x
You might want to take this a step further and encode the case switch using a type class:
class Fooer a where
foo :: a -> String -> IO [String]
data Mimsy = Mimsy
instance Fooer Mimsy where
foo _ x = undefined -- etc.
data Slithy = Slithy
instance Fooer Slithy where
foo _ x = undefined -- etc.
Another possibility is to use newtype wrappers around String and a Fooable class, akin to Lee Duhem's answer. Either way, using classes for that feels like overkill to me, so I'd stick with the simple sum type solution.
Yet another approach is using records of functions instead of type classes. That, too, is overkill here, though arguably less so than using classes:
data Fooer = Fooer { foo :: String -> IO [String] }
-- Export only mimsy and slithy, and not the Fooer constructor.
mimsy :: Fooer
mimsy = Fooer { foo = Mimsy.foo }
slithy :: Fooer
slithy = Fooer { foo = Slithy.foo }
I would change bar to take the auxiliary funcion directly as a parameter, instead of using a selector parameter.
bar :: (String -> IO [String]) -> String -> IO [String]
Outside the function (possibly in my Main.hs) I would construct the following map:
strategies :: M.Map String (String -> IO [String])
strategies = M.fromList [("A",A.foo), ("B",B.foo)]
This map allows us to decouple the aggregation of the known implementations from the selection of what implementation to use.
The process of looking into the map and constructing the actual bar' :: String -> IO [String] function in which we are interested should be relegated to the outermost layers of your program. That way, dependencies are minimized and "strategy not found" errors are detected sooner.
One possible solution is using user-defined typeclass, like this:
FooClass.hs
module FooClass (FooClass(..)) where
class FooClass a where
bar :: a -> IO [String]
A.hs
module A where
import FooClass
data A = A String deriving (Show)
foo :: A -> IO [String]
foo (A s) = return ["A", s]
instance FooClass A where
bar = foo
B.hs
module B where
import FooClass
data B = B String deriving (Show)
foo :: B -> IO [String]
foo (B s) = return ["B", s]
instance FooClass B where
bar = foo
After all those code, you can use them like this:
t.hs
import FooClass
import A
import B
main = do
a <- bar (A "bar")
b <- bar (B "bar")
putStrLn $ show (a, b)
Testing:
$ runhaskell t.hs
(["A","bar"],["B","bar"])
So I am trying to implement a Haskell game using the State and as a part of the game, I wanted to implement ways to save a current player's name and retrieve it when called. I have helper functions popStack and pushStack which pops and pushes values into stack respectively.
The current code:
import Control.Monad.State
data Gamestate = Gamestate {
gamestack :: [String],
gamememory :: String
}
type NewGameState = State GameState
popStack :: NewGameState String
popStack = state $ \st -> case gamestack st of
[] -> (0.0,st)
x:xs -> (x,st { gamestack = xs })
pushStack :: String -> NewGameState ()
push d = modify $ \st -> st { gamestack = d : gamestack st }
I have come up with the following code for saveName and getName.
saveName :: NewGameState ()
saveName = do
memory <-head
pushStack $ x
getName :: NewGameState ()
getName = do
memory <- head gamestack
popStack $ memory
The code snippets above return type errors. I don't understand State Monads much. So how do I copy the current players name at the top of the gamestack into gamememory using saveName and push the gamememory at the top of gamestack when I use getName?
Sorry if its a bit confusing. I am an ESL speaker. Thanks in advance.
I'm going to answer your question by showing you the idiomatic way to do what you are trying to do. As I go along I'm going to point out what I fixed in your code.
First problem: You have inconsistent capitalization of Gamestate. Capitalization matters in Haskell, so I renamed everything to GameState.
So after making that fixes, the first thing I did was define lenses to your two data type's fields. This makes it much easier do stateful things that modify a subset of your state. You will see this when I get to the implementations of the remaining functions:
import Control.Monad.State
import Control.Lens
data GameState = GameState
{ _gamestack :: [String]
, _gamememory :: String
}
gamestack :: Lens' GameState [String]
gamestack k (GameState s m) = fmap (\s' -> GameState s' m) (k s)
gamememory :: Lens' GameState String
gamememory k (GameState s m) = fmap (\m' -> GameState s m') (k m)
type NewGameState = State GameState
Note that you don't have to manually define lenses like this. Instead of defining gamememory and gamestack, you could also have done this instead:
{-# LANGUAGE TemplateHaskell #-} -- Note the extension
import Control.Lens
data GameState = GameState
{ _gamestack :: [String]
, _gamememory :: String
}
makeLenses ''GameState
Whichever way you choose, once we have these lenses, we can write push and pop in such a way that they don't care what state they are acting on, as long as it is a list:
pop :: State [a] (Maybe a)
pop = do
s <- get
case s of
[] -> return Nothing
x:xs -> do
put xs
return (Just x)
push :: a -> State [a] ()
push d = modify (d:)
Notice that I changed pop to return a Maybe if the list is empty. This is more idiomatic Haskell than defaulting to 0 or using head.
Using push and pop, it becomes very easy to transfer values between your game's memory and its stack:
saveName :: NewGameState ()
saveName = do
memory <- use gamememory
zoom gamestack (push memory)
getName :: NewGameState ()
getName = do
m <- zoom gamestack pop
case m of
Nothing -> return ()
Just x -> gamememory .= x
Notice how I use zoom to localize push and pop to operate on either the gamememory or the gamestack fields. zoom takes a lens to a sub-field and then runs the stateful action as if the entire state were just that sub-field. This is cool because now push and pop are much more reusable and we don't have to bake in a specific choice of state data type into them.
This also uses .=, which sets a given field. It's basically the same as:
lens .= x = zoom lens (put x)
To learn more about lenses, (.=), and zoom, you might want to read this post that I wrote.
Edit: By request, here is the lens-free version:
import Control.Monad.State
data GameState = GameState
{ gamestack :: [String]
, gamememory :: String
}
type NewGameState = State GameState
saveName :: NewGameState ()
saveName = do
GameState stack memory <- get
put (GameState (memory:stack) memory)
getName :: NewGameState ()
getName = do
GameState stack memory <- get
case stack of
[] -> put (GameState stack memory)
x:xs -> put (GameState xs x )
If something is on the right side of a <- than it has to be in that monad. So what you want here is something like
saveName :: NewGameState ()
saveName = do
memory <- fmap gamememory get
pushStack memory
getName = popStack
for saveName we fmap gamememory over the current state and store the result in memory than push that on the stack. We can actually write this as get >>= pushStack . gamememory if you want to be fancy.
popStack doesn't take any arguments so I'm not sure what you wanted there. My best guess is that it should just grab the last name we pushed on which just is a call to popStack.
NewGameState is a poor name - it isn't a new game state at all, it's a monad that carries around a state. I just called it Game.
pushStack vs push - You gave a signature named pushStack then a function named push. Pick one.
In popStack you have [] -> (0.0, st) Let's face it, 0.0 is not a string, so why are you trying to return it? Did you just not know what to do when popping an empty stack? How about you use "" instead?
saveName and getName Well you haven't even said what you want these to do. It seems you accepted other answerer's interpretations so going with that, we can just use record update syntax.
In the end, here is some code that at least compiles:
import Control.Monad.State
data GameState = GameState {
gamestack :: [String],
gamememory :: String
}
type Game = State GameState
popStack :: Game (Maybe String)
popStack = state $ \st -> case gamestack st of
[] -> (Nothing,st)
x:xs -> (Just x,st { gamestack = xs })
pushStack :: String -> Game ()
pushStack d = modify $ \st -> st { gamestack = d : gamestack st }
saveName :: Game ()
saveName = do
memory <- gamememory `fmap` get
pushStack memory
getName :: Game ()
getName = do
newMem <- popStack
case newMem of
Nothing -> return ()
Just n -> modify (\x -> x { gamememory = n } )