Inserting a value into a Set using stateful lenses - haskell

In yet another attempt to teach myself ekmett's lens library, I'm modifying a simple text-based hangman game to use lenses instead of record updates. The code itself works, but I've come across a place where I feel like I'm using the lens library incorrectly. This code works correctly, but it just doesn't look as elegant to me as all the lens tutorials I've seen.
First, my types:
data GameState = GameState
{ _guess :: Set Char
, _secret :: String
, _wrongGuesses :: Int
} deriving (Eq, Show)
makeLenses ''GameState
type Game a = StateT GameState IO a
The function I'm bothered by is where I process the guess obtained from the user:
nextGuess :: Game ()
nextGuess = do
gs <- get -- GameState
g <- getUserGuess :: Game Char
-- If the user guessed a letter that wasn't in the secret word
when (g `notElem` gs^.secret) $
-- increment the number of wrong guesses
wrongGuesses += 1
-- Insert that guess into the set of guesses
guess .= gs^.guess.to (insert g)
I'm mostly fine with the line
when (g `notElem` gs^.secret) $ wrongGuesses += 1
But the next line, where the guess is inserted into the current set of guesses seems like a roundabout way to do it. Having to get the current set, insert, then set it again just doesn't sound like the "lens way of doing things", especially when the line before all I have to do to increment the wrongGuesses counter is use += 1.
Is there a better way to do this?

Unless I'm much mistaken,
guess %= insert g
(%=) acts as modify and will feed the Set into insert g and then stick it back into guess.

Related

linear congruent generator in haskell

This is a very simple linear-congruent pseudo-random number generator. It works fine when I seed it, but I want to make it so that it self-seeds with every produced number. Problem is that I don't know how to do that in Haskell where the notion of variables does not exist. I can feed the produced number recursively, but then my result would be a list of integers instead of a single number.
linCongGen :: Int -> Int
linCongGen seed = ((2*seed) + 3) `mod` 100
I'll summarize the comments a bit more meaningfully. The simplest solution is, like you observed, an infinite list of the sequence of generated elements. Then, every time you want to get a new number, pop off the head of that list.
linCongGen :: Integral a => a -> [a]
linCongGen = iterate $ \x -> ((2*x) + 3) `mod` 100
That said, here is a solution (which I do not agree with), but which does what I think you want. For mutable state, we usually use IORef, which is sort of like a reference or pointer. Here is the code. Please read the disclaimer afterwards though.
import Data.IORef
import System.IO.Unsafe
seed :: IORef Int
seed = unsafePerformIO $ newIORef 71
linCongGen :: IO Int
linCongGen = do previous <- readIORef seed
modifyIORef' seed $ \x -> ((2*x) + 3) `mod` 100
return previous
And here is a sample usage printing out the first hundred numbers generated: main = replicateM_ 100 $ getRandom >>= print (you'll need to have Control.Monad imported too for replicateM_).
DISCLAIMER
This is a bit of a hacky approach described here. As the link says "Maybe the need for global mutable state is a symptom of bad design." The link also has a good description of a more intelligent workaround. Making an IORef is an inherently IO operation, and we really shouldn't be using unsafePerformIO on it. If you find yourself fighting Haskell in this way, it's because Haskell was designed to get in your way when you are doing things you shouldn't.
That said, I find comfort in knowing that this approach is also the one using in System.Random (the standard random number module) to define the initial seed (check out the source).

Accessing vector element by index using lens

I'm looking for a way to reference an element of a vector using lens library...
Let me try to explain what I'm trying to achieve using a simplified example of my code.
I'm working in this monad transformer stack (where StateT is the focus, everything else is not important)
newtype MyType a = MyType (StateT MyState (ExceptT String IO) a)
MyState has a lot of fields but one of those is a vector of clients which is a data type I defined:
data MyState = MyState { ...
, _clients :: V.Vector ClientT
}
Whenever I need to access one of my clients I tend to do it like this:
import Control.Lens (use)
c <- use clients
let neededClient = c V.! someIndex
... -- calculate something, update client if needed
clients %= (V.// [(someIndex, updatedClient)])
Now, here is what I'm looking for: I would like my function to receive a "reference" to the client I'm interested in and use it (retrieve it from State, update it if needed).
In order to clear up what I mean here is a snippet (that won't compile even in pseudo code):
...
myFunction (clients.ix 0)
...
myFunction clientLens = do
c <- use clientLens -- I would like to access a client in the vector
... -- calculate stuff
clientLens .= updatedClient
Basically, I would like to pass to myFunction something from Lens library (I don't know what I'm passing here... Lens? Traversal? Getting? some other thingy?) which will allow me to point at particular element in the vector which is kept in my StateT. Is it at all possible? Currently, when using "clients.ix 0" I get an error that my ClientT is not an instance of Monoid.
It is a very dumbed down version of what I have. In order to answer the question "why I need it this way" requires a lot more explanation. I'm interested if it is possible to pass this "reference" which will point to some element in my vector which is kept in State.
clients.ix 0 is a traversal. In particular, traversals are setters, so setting and modifying should work fine:
clients.ix 0 .= updatedClient
Your problem is with use. Because a traversal doesn't necessarily contain exactly one value, when you use a traversal (or use some other getter function on it), it combines all the values assuming they are of a Monoid type.
In particular,
use (clients.ix n)
would want to return mempty if n is out of bounds.
Instead, you can use the preuse function, which discards all but the first target of a traversal (or more generally, a fold), and wraps it in a Maybe. E.g.
Just c <- preuse (clients.ix n)
Note this will give a pattern match error if n is out of bounds, since preuse returns Nothing then.

How should I organize normal and "state" versions of functions in the state monad?

I decided to try the State Monad to try and clean up some of the projects that I've started. I ran into a naming/compartmentalization problem.
If I have the following objects:
data Obj = Player { oPos :: Point }
data World = World { wKeys :: [Key], wPlayer :: Obj }
I might have a convenience function like:
setPlayer :: Obj -> World -> World
setPlayer o w = w{wPlayer = o}
and a matching state operation like:
setPlayerW :: Obj -> WorldState ()
setPlayerW o = get >>= put . setPlayer o
which uses the other convenience function; for convenience.
What is the typical naming convention for something like this? I post-pended the state version with a W, but that's kind of ugly.
And are the "state-versions" typical segregated from the "object-versions" in a separate file?
Am I going about this wrong completely? Is there a better set-up then having 2 different versions of any operations I might need?
Personally, I wouldn't have a separate function for the state version myself. Instead, use the modify function instead:
do let o = player
modify (setPlayer o)
something else
In a sense, the naming convention you're looking for would just be the same as using modify except folded into the names of each function. When I find myself naming functions like this, I generally try to find some way to organize them in the language instead of using their names. Sometimes, like here, an existing function is all you need; other times, it involves creating a function of your own to achieve the same end or extracting things into a module.
The core idea is that it's better to reify patterns in your code using first-class language constructs instead of encoding them indirectly into the names. (Of course, if this ends up really awkward, you shouldn't do it, but it's fine here.)
This looks like a good time to introduce the lens library. This is a bit of a daunting library at first, and I still struggle with some of its more complex features (the rabbit hole is pretty deep for this one), but it can really simplify a lot of your State code. To use it, it's recommended to change your data types a bit first so you can utilize template haskell:
import Control.Monad
import Control.Monad.State
import Control.Lens
-- Made assumption on what Point would look like
data Point = Point { _x :: Int, _y :: Int } deriving (Eq, Show)
data Obj = Player { _oPos :: Point } deriving (Eq, Show)
data World = World { _wKeys :: [Key], _wPlayer :: Obj } deriving (Eq, Show)
makeLenses ''Point
makeLenses ''Obj
makeLenses ''World
-- Also assumed this type
type WorldState = StateT World IO
Then you can write code that looks very much imperative using the generated lenses
setPlayerW :: Obj -> WorldState ()
setPlayerW o = wPlayer .= o
Or if you want the non-monadic version
setPlayer :: Obj -> World -> World
setPlayer o = wPlayer .~ o
So this uses the .= operator to set the wPlayer field of the World state to the new value. More impressively, you could use it to write code like
moveUp, moveDown, moveLeft, moveRight :: WorldState ()
moveUp = wPlayer.oPos.y += 1
moveDown = wPlayer.oPos.y -= 1
moveLeft = wPlayer.oPos.x -= 1
moveRight = wPlayer.oPos.x += 1
Which makes it look a lot like an object oriented language using normal function composition. A quick test:
game :: WorldState ()
game = do
replicateM_ 3 moveUp
replicateM_ 5 moveLeft
replicateM_ 10 moveRight
replicateM_ 6 moveDown
> execStateT game $ World [] $ Player $ Point 0 0
World {_wKeys = [], _wPlayer = Player {_oPos = Point {_x = 5, _y = -3}}}
There are a lot of really interesting and useful operators in the lens library, and there's a lot of support built-in for using it with StateT stacks.
Another nice feature is the zoom function, which takes a lens and "zooms in" on it, letting you operate as if your state has the value of whatever you zoomed onto. An example would be
game = zoom (wPlayer.oPos) $ do
y += 3
x -= 5
x += 10
y -= 6
And this would produce the same result as before. This is generally more efficient (fewer layers to unwrap at each step) and can be much cleaner.

Haskell--Manipulating data within a tuple

I'm attempting to simulate a checkers game using haskell. I am given a 4-tuple named, checkersState, that I would like to manipulate with a few different functions. So far, I have a function, oneMove, that receives input from checkerState and should return a tuple of the modified data:
The Input Tuple:
(
3600,
"",
[
"----------",
"------r---",
"----------",
"----------",
"---r-r----",
"------r---",
"---w---w-w",
"----------",
"----------",
"------w---"
],
(
49
,
43
)
)
So far I have something similar to below defining my function but am unsure how to access the individual members within the tuple checkerState. This method will take a time, array of captured pieces, board, and move to make, and return a time, array of captured pieces, and board. Currently, I would like to modify the time (INT) in the tuple depending on the state of the board:
onemove :: (Int,[Char],[[Char]],(Int,Int)) -> (Int,[Char],[[Char]])
Thanks in advance!
You can use pattern-matching to pull out the elements, do whatever changes need to be made, and pack them back into a tuple. For example, if you wanted to increment the first value, you could:
onemove (a,b,c,d) = (a + 1,b,c,d)
If you find yourself doing this a lot, you might reconsider using a tuple and instead use a data type:
data CheckersState = CheckersState { time :: Int -- field names are just
, steps :: [Char] -- guesses; change them
, board :: [[Char]] -- to something that
, pos :: (Int, Int) -- makes sense
} deriving (Eq, Read, Show)
Then you can update it with a much more convenient syntax:
onemove state = state { time = time state + 1 }
If you want to stick with tuples and you happen to be using lenses, there’s another easy way to update your tuple:
onemove = over _1 (+1)
Or if you’re using lenses and your own data type (with an appropriately-defined accessor like the one provided), you can do something similar:
_time :: Lens' CheckersState Int
_time f state = (\newTime -> state { time = newTime }) <$> f (time state)
onemove = over _time (+1)
So there’s plenty of fancy ways to do it. But the most general way is to use pattern-matching.
As icktoofay is saying, using tuples is a code smell, and records with named components is way better.
Also, using Char (and String) is a code smell. To repair it, define a data type that precisely describes what you expect in a cell of the board, like data Colour = None | Red | Black, but see next item.
And, using Lists is also a code smell. You actually want something like type Board = Data.Map.Map Pos Colour or Data.Map.Map Pos (Maybe Colour') with data Colour' = Red | Black.
Oh, and Int is also a code smell. You could define newtype Row = Row Int ; newtype Col = Col Int ; type Pos = (Row,Col). Possibly deriving Num for the newtypes, but it's not clear, e.g., you don't want to multiply row numbers. Perhaps deriving (Eq,Ord,Enum) is enough, with Enum you get pred and succ.
(Ah - this Pos is using a tuple, thus it`s smelly? Well, no, 2-tuples is allowed, sometimes.)
You use pattern matching to decompose the tuple into variables.
onemove (i, c, board, (x, y)) = <do something> (i, c, board)
However, you should define a separate data structure for the board to make your intention clear. I don't know what the meaning of the first two values. See: http://learnyouahaskell.com/making-our-own-types-and-typeclasses

Storing values in a data structure Haskell

I'm trying to store randomly generated dice values in some data structure, but don't know how exactly to do it in Haskell. I have so far, only been able to generate random ints, but I want to be able to compare them to the corresponding color values and store the colors instead (can't really conceive what the function would look like). Here is the code I have --
module Main where
import System.IO
import System.Random
import Data.List
diceColor = [("Black",1),("Green",2),("Purple",3),("Red",4),("White",5),("Yellow",6)]
diceRoll = []
rand :: Int -> [Int] -> IO ()
rand n rlst = do
num <- randomRIO (1::Int, 6)
if n == 0
then printList rlst -- here is where I need to do something to store the values
else rand (n-1) (num:rlst)
printList x = putStrLn (show (sort x))
--matchColor x = doSomething()
main :: IO ()
main = do
--hSetBuffering stdin LineBuffering
putStrLn "roll, keep, score?"
cmd <- getLine
doYahtzee cmd
--rand (read cmd) []
doYahtzee :: String -> IO ()
doYahtzee cmd = do
if cmd == "roll"
then do rand 5 []
else putStrLn "Whatever"
After this, I want to be able to give the user the ability to keep identical dices (as in accumulate points for it) and give them a choice to re-roll the left over dices - I'm thinking this can done by traversing the data structure (with the dice values) and counting the repeating dices as points and storing them in yet another data structure. If the user chooses to re-roll he must be able to call random again and replace values in the original data structure.
I'm coming from an OOP background and Haskell is new territory for me. Help is much appreciated.
So, several questions, lets take them one by one :
First : How to generate something else than integers with the functions from System.Random (which is a slow generator, but for your application, performance isn't vital).
There is several approaches, with your list, you would have to write a function intToColor :
intToColor :: Int -> String
intToColor n = head . filter (\p -> snd p == n) $ [("Black",1),("Green",2),("Purple",3),("Red",4),("White",5),("Yellow",6)]
Not really nice. Though you could do better if you wrote the pair in the (key, value) order instead since there's a little bit of support for "association list" in Data.List with the lookup function :
intToColor n = fromJust . lookup n $ [(1,"Black"),(2,"Green"),(3,"Purple"),(4,"Red"),(5,"White"),(6,"Yellow")]
Or of course you could just forget this business of Int key from 1 to 6 in a list since lists are already indexed by Int :
intToColor n = ["Black","Green","Purple","Red","White","Yellow"] !! n
(note that this function is a bit different since intToColor 0 is "Black" now rather than intToColor 1, but this is not really important given your objective, if it really shock you, you can write "!! (n-1)" instead)
But since your colors are not really Strings and more like symbols, you should probably create a Color type :
data Color = Black | Green | Purple | Red | White | Yellow deriving (Eq, Ord, Show, Read, Enum)
So now Black is a value of type Color, you can use it anywhere in your program (and GHC will protest if you write Blak) and thanks to the magic of automatic derivation, you can compare Color values, or show them, or use toEnum to convert an Int into a Color !
So now you can write :
randColorIO :: IO Color
randColorIO = do
n <- randomRIO (0,5)
return (toEnum n)
Second, you want to store dice values (colors) in a data structure and give the option to keep identical throws. So first you should stock the results of several throws, given the maximum number of simultaneous throws (5) and the complexity of your data, a simple list is plenty and given the number of functions to handle lists in Haskell, it is the good choice.
So you want to throws several dices :
nThrows :: Int -> IO [Color]
nThrows 0 = return []
nThrows n = do
c <- randColorIO
rest <- nThrows (n-1)
return (c : rest)
That's a good first approach, that's what you do, more or less, except you use if instead of pattern matching and you have an explicit accumulator argument (were you going for a tail recursion ?), not really better except for strict accumulator (Int rather than lists).
Of course, Haskell promotes higher-order functions rather than direct recursion, so let's see the combinators, searching "Int -> IO a -> IO [a]" with Hoogle gives you :
replicateM :: Monad m => Int -> m a -> m [a]
Which does exactly what you want :
nThrows n = replicateM n randColorIO
(I'm not sure I would even write this as a function since I find the explicit expression clearer and almost as short)
Once you have the results of the throws, you should check which are identical, I propose you look at sort, group, map and length to achieve this objective (transforming your list of results in a list of list of identical results, not the most efficient of data structure but at this scale, the most appropriate choice). Then keeping the colors you got several time is just a matter of using filter.
Then you should write some more functions to handle interaction and scoring :
type Score = Int
yahtzee :: IO Score
yahtzeeStep :: Int -> [[Color]] -> IO [[Color]] -- recursive
scoring :: [[Color]] -> Score
So I recommend to keep and transmit a [[Color]] to keeps track of what was put aside. This should be enough for your needs.
You are basically asking two different questions here. The first question can be answered with a function like getColor n = fst . head $ filter (\x -> snd x == n) diceColor.
Your second question, however, is much more interesting. You can't replace elements. You need a function that can call itself recursively, and this function will be driving your game. It needs to accept as parameters the current score and the list of kept dice. On entry the score will be zero and the kept dice list will be empty. It will then roll as many dice as needed to fill the list (I'm not familiar with the rules of Yahtzee), output it to the user, and ask for choice. If the user chooses to end the game, the function returns the score. If he chooses to keep some dice, the function calls itself with the current score and the list of kept dice. So, to sum it up, playGame :: Score -> [Dice] -> IO Score.
Disclaimer: I am, too, very much a beginner in Haskell.
at first thought:
rand :: Int -> IO [Int]
rand n = mapM id (take n (repeat (randomRIO (1::Int, 6))))
although the haskellers could remove the parens

Resources