Trouble with the State Monad - haskell

I am trying to write a program to generate 'word chains', e.g. bat -> cat -> cot -> bot, using the list monad (mostly comprehensions) to generate combinations of words, and the state monad to build up the actual chain as i go through the possibilities. That second part is giving me trouble:
import Control.Monad.State
type Word = String
type Chain = [Word]
getNext :: Word -> State Chain Word
getNext word = do
list <- get
return (list ++ "current word")
The part where I generate words works and is given below, but as you can see I don't really know what I'm doing in this part. Basically wordVariations :: Word -> [Word] takes a Word and returns a list of Words that differ in one letter from the given word. I'm trying to change this so that each word has a state signifying its predecessors:
For example: input = "cat". the final value is "got", the final state is ["cat","cot","got"]
What I have now will give me "got" from "cat" after 3 steps, but won't tell me how it got there.
None of the State Monad tutorials I found online were terribly helpful. The above code, when compiled with GHC, gives the error:
WordChain.hs:42:11:
Couldn't match type `Word' with `Char'
When using functional dependencies to combine
MonadState s (StateT s m),
arising from the dependency `m -> s'
in the instance declaration in `Control.Monad.State.Class'
MonadState [Char] (StateT Chain Data.Functor.Identity.Identity),
arising from a use of `get' at WordChain.hs:42:11-13
In a stmt of a 'do' block: list <- get
In the expression:
do { list <- get;
return (list ++ "current word") }
Failed, modules loaded: none.
This is just meant to be a test to work off of, but I can't figure it out!
The code in full is below in case it is helpful. I know this may not be the smartest way to do this, but it is a good opportunity to learn about the state monad. I am open to necessary changes in the way the code works also, because I suspect that some major refactoring will be called for:
import Control.Monad.State
type Word = String
type Dict = [String]
-- data Chain = Chain [Word] deriving (Show)
replaceAtIndex :: Int -> a -> [a] -> [a]
replaceAtIndex n item ls = a ++ (item:b) where (a, (_:b)) = splitAt n ls
tryLetter str c = [replaceAtIndex n c str | n <- [0..(length str - 1)]]
wordVariations str = tryLetter str =<< ['a' .. 'z']
testDict :: Dict
testDict = ["cat","cog","cot","dog"]
------- implement state to record chain
type Chain = [Word] -- [cat,cot,got,tot], etc. state var.
startingState = [""] :: Chain
getNext :: Word -> State Chain Word
getNext w = do
list <- get
return ( list ++ "current word")

First of all, the error you posted is in this line return ( list ++ "current word").
"current word" type is Word, which is an alias for String, which is an alias for[Char]`.
The variable list has a type of Chain, which is an alias for [Word], which is an alias for [[Char]].
The type signature of the function forces the return type must be a Word.
++ requires that the types on both sides be a list with the same type, (++) :: [a] -> [a] -> [a].
However, if you plug in the above type signatures, you get the type [Word] -> [Char] -> [Char] which has mismatched "a"s.
Quick but fairly important performance side note: prepending to a list is much faster then appending, so you might want to consider building them backwards and using (:) and reversing them at the end.
The State Monad is not really the right choice for storing the steps used to get to the result. At least it is certainly overkill, when the List Monad would be sufficient to complete the task. Consider:
-- given a list of words, find all possible subsequent lists of words
getNext :: [String] -> [[String]]
getNext words#(newest:_) = fmap (:words) (wordVariations newest)
-- lazily construct all chains of every length for every word
wordChains :: String -> [[[String]]]
wordChains word = chain
where chain = [[word]] : map (>>= getNext) chain
-- all the 5 word long chains starting with the word "bat"
batchains = wordChains "bat" !! 4
(Disclaimer: code compiled, but not run).
getNext takes a Chain, and returns a list containing a list of Chains, where each one has a different prepended successor in the chain. Since they share a common tail, this is memory efficient.
In wordChains, by repeatedly mapping using the list monad with (>>= getNext), you end up with a lazy infinite list, where the zeroth item is a Chain the starting word, the first item is all 2 item Chains where the first is the starting word, the second item is all 3 item chains, and so on. If you just want one chain of length 5, you can grab the head of the 4th item, and it will do just enough computation to create that for you, but you can also get all of them.
Also, getNext could be expanded to not repeat words by filtering.
Finally, when it comes to finding wordVariations, another algorithm would be to construct a filter which returns True if the lengths of two words are the same and the number of characters that are different between them is exactly 1. Then you could filter over a dictionary, instead of trying every possible letter variation.
Good luck!

Related

Creating a conditioned Arbitrary instance ( * Ambiguous type variable `a' arising from a use of `quickCheck')

I have this test I want to make:
prop_inverse_stringsToInts st = isDigitList st ==> st == map show (stringsToInts st)
Which is testing a function that converts a list of Strings to a list of Integers, but of course the strings need to be digits so I created a pre-condition that checks that using the isDigitList function I made, but the condition is too specific and quickCheck gives up : "*** Gave up! Passed only 43 tests; 1000 discarded tests."
So I wanted to create an Arbitrary instance for my case, but the thing is I am inexperienced with working with Arbitrary, so I don't really know how to do this and every time I shuffle code I get a new error. All I want is an Arbitrary that only returns the Foo [String] if it passes the isDigitList (which receives a [String] and returns a Bool). So far I have something like this :
Foo a = Foo [String] deriving (Show,Eq)
instance (Arbitrary a) => Arbitrary (Foo a ) where
arbitrary = do
st <- (arbitrary :: Gen [String])
if isDigitList st
then do return (Foo st)
else do return (Foo []) -- This is probably a bad idea
I altered my property to :
prop_inverse_stringsToInts :: Foo a -> Bool
prop_inverse_stringsToInts (Foo st) = st == map show (stringsToInts st)
But now I am getting the error "* Ambiguous type variable a0' arising from a use of `quickCheck'" even though I am running quickCheck like this : > quickCheck (prop_inverse_stringsToInts :: Foo a -> Bool)
Can someone help please? Thank you in advance!
It seems you know the basics, but I'll repeat them here just to be sure. There are two ways to get QuickCheck to generate the inputs you want:
Have it generate some inputs and then filter out ones you don't want, or
Have it generate only the inputs you want.
You started with option 1, but as you saw, that didn't work out great. Compared to all possible lists of String, there really aren't that many that are digit lists. The better option is to generate only the inputs you want.
To succeed at option 2, you need to make a generator, which would be a value of type Gen [String] that generates lists of Strings that fit your criteria. The generator you propose still uses the method of filtering, so you may want to try a different approach. Consider instead, something like:
genDigitStrings :: Gen [String]
genDigitStrings = do
intList <- arbitrary :: Gen [Integer]
return $ fmap show intList
This generator produces arbitrary lists of Strings that are always shown integers, meaning that they will always be digit lists. You can then go ahead and insert this into an Arbitrary instance for some newtype if you want.
For your own sanity, you can even check your work with a test like this:
propReallyActuallyDigitStrings = forAll genDigitStrings isDigitList
If that passes, you have some confidence that your generator really only produces digit lists, and if it fails, then you should adjust your generator.

Haskell Programming Assignment, "Couldn't match expected type ‘Int’ with actual type ‘[a0] -> Int’ "and a few more Errors

The assignment I have: A function numOccurences that takes a value and a list, returning the number of times that value appears in the list. I am learning haskell and am getting frustrated, this is my code for this:
numOccurences:: b -> [a] -> Int
numOccurences n [ls]
|([ls] !! n==True) = (numOccurences(n (tail [ls])))+1
|otherwise = 0
The errors I am getting are as follows:
https://imgur.com/a/0lTBn
A few pointers:
First, in your type signature, using different type variables (i.e. b and a) creates the possibility that you could look for occurrences of a value of one type, in a list with another type, which in this case is not what you want. So instead of two type variables, you just want to use one.
Second, whatever the concrete type of your list is, whether it's [Char], [Int], etc., it needs to be equatable (i.e. it needs to derive the Eq typeclass), so it makes sense to use the class constraint (Eq a) => in your type signature.
Third, since we're traversing a list, let's use pattern matching to safely break off the first element of the list for comparison, and let's also add a base case (i.e. what we do with an empty list), since we're using recursion, and we only want the recursive pattern to match as long as there are elements in our list.
Lastly, try to avoid using indexing (i.e. !!), where you can avoid it, and use pattern matching instead, as it's safer and easier to reason about.
Here's how your modified function might look, based on the above pointers:
numOccurences :: (Eq a) => a -> [a] -> Int
numOccurences _ [] = 0
numOccurences n (x:xs)
| n == x = 1 + numOccurences n xs
| otherwise = numOccurences n xs

Get a random list item in Haskell

After reviewing this SO question I am trying to use the random number generator to return a random list item based on the return of the randomIO generator.
Full Code:
module Randomizer where
import System.IO
import System.Random
data Action = Create | Destroy
deriving (Enum, Eq, Show)
type History = [Action]
-- | this looks at three sets of histories, and returns an appropriate Action
type ThreeHistoryDecisionMaker = History -> History -> History -> Action
allThreeDecisionMakers :: [ThreeHistoryDecisionMaker]
allThreeDecisionMakers = [decision1, decision2, decision3, decision4, decision5]
chooseRandomDecision :: [ThreeHistoryDecisionMaker] -> Int -> Strategy3P
chooseRandomDecision = allThreeDecisionMakers !! randomIO(0,4)
But I get the following errors:
special_program1.hs:249:16:
Couldn't match type ‘Action’
with ‘History -> History -> History -> Action’
Expected type: [[ThreeHistoryDecisionMaker] -> Int -> ThreeHistoryDecisionMaker]
Actual type: [ThreeHistoryDecisionMaker]
In the first argument of ‘(!!)’, namely ‘allThreeDecisionMakers’
In the expression: all3PStrategies !! randomIO (0, 4)
special_program1.hs:249:35:
Couldn't match expected type ‘(t0, t1) -> Int’
with actual type ‘IO a0’
The function ‘randomIO’ is applied to one argument,
but its type ‘IO a0’ has none
In the second argument of ‘(!!)’, namely ‘randomIO (0, 4)’
In the expression: all3PStrategies !! randomIO (0, 4)
Why is the first error block wanting to expect a list of everything inside it?
What does the second code block mean?
randomIO is not a "random function". Such a thing doesn't exist in Haskell, it wouldn't be referentially transparent. Instead, as the name suggests, it's an IO action which can yield a random value. It makes no sense to index a list with an IO action, !! randomIO(0,4) isn't possible. (It's impossible also for another reason: randomIO creates unlimited values, you want randomRIO (with an R for "range parameter") if you need to specify a (0,4) range.)
What you need to to do to get the value yielded by the action: well, monads! If you haven't learned the theory about those yet, never mind. A random-indexer could look thus:
atRandIndex :: [a] -> IO a -- note that this is gives itself an IO action
atRandIndex l = do
i <- randomRIO (0, length l - 1)
return $ l !! i
I suggest you actually use that function to implement your task.
But back to the code you posted... there's more problems. If you specify the type of chooseRandomDecision with two arguments, then you need to actually define it as a function of these arguments! But your definition doesn't accept any arguments at all, it merely uses the globally-defined list allThreeDecisionMakers (use of global variables never needs to be stated in the type).
Moreover, if you're choosing from a list of THDMakers, then the resulting element will also have that type, what else! So unless Strategy3P is simply another synonym of History -> History -> History -> Action, this won't do as a result, even if you contain it in the right monad.
This answer offers a simple, effective solution to the problem posed in the title: "Get a random list item in Haskell".
The package Test.QuickCeck provides a number of helpful, straightforward functions for generating random values (http://hackage.haskell.org/package/QuickCheck-2.7.6/docs/Test-QuickCheck.html#g:5). A function that returns random values from a list (wrapped IO) can be built by composing the QuickTest functions elements and generate:
import Test.QuickCheck (generate, elements)
randItem :: [a] -> IO a
randItem = generate . elements
chris Frisina's function chooseRandomDecision would then look like this:
chooseRandomDecision :: [ThreeHistoryDecisionMaker] -> IO ThreeHistoryDecisionMaker
chooseRandomDecision = randItem
The user Cale in the #haskell channel on freenode helped coach me to this solution.
note: This solution works with QuickCheck 2.7.6, but needs some alteration for earlier versions. You can update to the latest version with cabal install QuickCheck. See this question.

Define a haskell function [IO a] -> IO[a]

I am doing a haskell exercise, regarding define a function accumulate :: [IO a] -> IO [a]
which performs a sequence of interactions and accumulates their result in a list.
What makes me confused is how to express a list of IO a ? (action:actions)??
how to write recursive codes using IO??
This is my code, but these exists some problem...
accumulate :: [IO a] -> IO [a]
accumulate (action:actions) = do
value <- action
list <- accumulate (action:actions)
return (convert_to_list value list)
convert_to_list:: Num a =>a -> [a]-> [a]
convert_to_list a [] = a:[]
convert_to_list x xs = x:xs
What you are trying to implement is sequence from Control.Monad.
Just to let you find the answer instead of giving it, try searching for [IO a] -> IO [a] on hoogle (there's a Source link on the right hand side of the page when you've chosen a function).
Try to see in your code what happens when list of actions is empty list and see what does sequence do to take care of that.
There is already such function in Control.Monad and it called sequence (no you shouldn't look at it). You should denote the important decision taken during naming of it. Technically [IO a] says nothing about in which order those Monads should be attached to each other, but name sequence puts a meaning of sequential attaching.
As for the solving you problem. I'd suggest to look more at types and took advice of #sacundim. In GHCi (interpreter from Glasgow Haskell Compiler) there is pretty nice way to check type and thus understand expression (:t (:) will return (:) :: a -> [a] -> [a] which should remind you one of you own function but with less restrictive types).
First of all I'd try to see at what you have showed with more simple example.
data MyWrap a = MyWrap a
accumulate :: [MyWrap a] -> MyWrap [a]
accumulate (action:actions) = MyWrap (convert_to_list value values) where
MyWrap value = action -- use the pattern matching to unwrap value from action
-- other variant is:
-- value = case action of
-- MyWrap x -> x
MyWrap values = accumulate (action:actions)
I've made the same mistake that you did on purpose but with small difference (values is a hint). As you probably already have been told you could try to interpret any of you program by trying to inline appropriate functions definitions. I.e. match definitions on the left side of equality sign (=) and replace it with its right side. In your case you have infinite cycle. Try to solve it on this sample or your and I think you'll understand (btw your problem might be just a typo).
Update: Don't be scary when your program will fall in runtime with message about pattern match. Just think of case when you call your function as accumulate []
Possibly you looking for sequence function that maps [m a] -> m [a]?
So the short version of the answer to your question is, there's (almost) nothing wrong with your code.
First of all, it typechecks:
Prelude> let accumulate (action:actions) = do { value <- action ;
list <- accumulate (action:actions) ; return (value:list) }
Prelude> :t accumulate
accumulate :: (Monad m) => [m t] -> m [t]
Why did I use return (value:list) there? Look at your second function, it's just (:). Calling g
g a [] = a:[]
g a xs = a:xs
is the same as calling (:) with the same arguments. This is what's known as "eta reduction": (\x-> g x) === g (read === as "is equivalent").
So now just one problem remains with your code. You've already taken a value value <- action out of the action, so why do you reuse that action in list <- accumulate (action:actions)? Do you really have to? Right now you have, e.g.,
accumulate [a,b,c] ===
do { v1<-a; ls<-accumulate [a,b,c]; return (v1:ls) } ===
do { v1<-a; v2<-a; ls<-accumulate [a,b,c]; return (v1:v2:ls) } ===
do { v1<-a; v2<-a; v3<-a; ls<-accumulate [a,b,c]; return (v1:v2:v3:ls) } ===
.....
One simple fix and you're there.

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