Recursive convert a 3-tuple to a char - Haskell - haskell

Given this function, I was wondering how one would approach this problem
convertChar' :: [[(Int, Int, Int)]] -> [[Char]]
I have the following helper functions, not sure if they're needed
toList :: [[(Int, Int, Int)]] -> [(Int, Int, Int)]
toList [(x)] = (x)
convertList :: [(Int, Int, Int)] -> [[(Int, Int, Int)]]
convertList x = [x]
The (Int, Int, Int) will either be (1, 1, 1) or (0, 0, 0)
If the tuple is (1, 1, 1) it will return the █ char.
If the tuple is (0, 0, 0) it will return " "
I was wondering what the smart way to approach this is.
Would I have to convert the original input from [[()]] to [()]
Apply the functions and then convert back to [[()]] before calling the converChar function recursively again?

The best answer I can come up with is that you should probably change your program so that your types represent what you want. Specifically, when I look at your code it seems that you have (or at least you think/you don’t have but wrote the wrong program):
Every [[(Int,Int,Int)]] is a list of the form [xs]
Every (Int,Int,Int) is either (0,0,0) or (1,1,1)
Firstly I will write down a solution to your problem as stated. Secondly I will show you how to construct types that represent the state of the wold (and don’t allow you to represent illegal states).
renderThing (0,0,0) = ' '
renderThing (1,1,1) = '█'
renderState = map (map renderThing)
Let’s describe this briefly. The first two lines define a partial function to do what your int-triple-to-char function, as described in the parent.
The third line defines the function you want. Let’s read it from left to right:
To renderState (which will have type [[(Int,Int,Int)]] -> [[Char]]):
Apply the map renderThing :: [(Int,Int,Int)] -> [Char] to each element of the list passed as input
To do that function, apply renderThing to each element of the inner list (I assume this is a row)
Unfortunately your program will crash if you ever violate your implicit invariant that any (Int,Int,Int) is either (0,0,0), or (1,1,1). One better type could be (Bool,Bool,Bool) as each element can then only have one of two values. Another way you could do this is:
data Thing = White | Black
There are two ways to put this into your program. Either use good types throughout so the compiler can make sure you never end up in an unexpected state, or you can have conversion functions which can have errors:
renderableBoard :: [[(Int,Int,Int)]] -> Either String [[Thing]]
renderableBoard = mapM (mapM convertOne) where
convertOne (0,0,0) = White
convertOne (1,1,1) = Black
convertOne x = "cannot concert to thing: " ++ show x

Related

Converting String to Tuple Haskell

I'm trying to create a function for a board game that will read a position on the board as a string and convert to a coordinate that can be used in the program e.g. "D4 => (3,3), "F2" => (5,1)".
So far I have this:
getCoord :: String -> Maybe(Int, Int)
getCoord s =
let alphas = "ABCDEFGH"
coord1 = head(s)
coord2 = tail(s)
in ((elemIndex coord1 alphas)-1, read(head coord2)-1)
I'm still learning about the use of Maybe in Haskell and am encountering the error:
• Couldn't match expected type ‘Maybe (Int, Int)’
with actual type ‘(Maybe Int, Integer)’
• In the expression:
((elemIndex coord1 alphas) - 1, read (head coord2) - 1)
Would appreciate your help on where I might be going wrong.
Thanks!
The problem you're facing is that elemIndex returns a Maybe Int. Since you're also trying to return a Maybe type, the best way to work with this is using a do block to perform operations inside the Maybe monad. This lets you use Maybe values as if they were normal values as long as your output will get wrapped back up in a Maybe. (If you need more information about how monads work, there are plenty of good answers here explaining it, and lots of other great posts across the internet.)
import Text.Read (readMaybe)
import Data.List (elemIndex)
getCoords :: String -> Maybe(Int, Int)
getCoords (coord1:coord2) = do
let alphas = "ABCDEFGH"
row <- elemIndex coord1 alphas
col <- readMaybe coord2
return (row, col - 1)
getCoords _ = Nothing
Note a couple other differences from your original.
The use of readMaybe instead of read. readMaybe is a special version of read that returns a value of type Maybe a. Since we're already working in a Maybe context, it's better to have a no-parse return Nothing than throw an error.
No - 1 on the row. elemIndex already has the behavior you want, i.e. A will return 0, etc.
Pattern match instead of head and tail. This lets you account for the case where the string is empty.
Extra definition to match empty list and return Nothing. The advantage of using a Maybe type is that you can return a value for errors instead of getting a Runtime error. In order to make use of that, we have to make sure we handle all of the cases.

Do notation for monad in function returning a different type

Is there a way to write do notation for a monad in a function which the return type isn't of said monad?
I have a main function doing most of the logic of the code, supplemented by another function which does some calculations for it in the middle. The supplementary function might fail, which is why it is returning a Maybe value. I'm looking to use the do notation for the returned values in the main function. Giving a generic example:
-- does some computation to two Ints which might fail
compute :: Int -> Int -> Maybe Int
-- actual logic
main :: Int -> Int -> Int
main x y = do
first <- compute x y
second <- compute (x+2) (y+2)
third <- compute (x+4) (y+4)
-- does some Int calculation to first, second and third
What I intend is for first, second, and third to have the actual Int values, taken out of the Maybe context, but doing the way above makes Haskell complain about not being able to match types of Maybe Int with Int.
Is there a way to do this? Or am I heading towards the wrong direction?
Pardon me if some terminology is wrongly used, I'm new to Haskell and still trying to wrap my head around everything.
EDIT
main has to return an Int, without being wrapped in Maybe, as there is another part of the code using the result of mainas Int. The results of a single compute might fail, but they should collectively pass (i.e. at least one would pass) in main, and what I'm looking for is a way to use do notation to take them out of Maybe, do some simple Int calculations to them (e.g. possibly treating any Nothing returned as 0), and return the final value as just Int.
Well the signature is in essence wrong. The result should be a Maybe Int:
main :: Int -> Int -> Maybe Int
main x y = do
first <- compute x y
second <- compute (x+2) (y+2)
third <- compute (x+4) (y+4)
return (first + second + third)
For example here we return (first + second + third), and the return will wrap these in a Just data constructor.
This is because your do block, implicitly uses the >>= of the Monad Maybe, which is defined as:
instance Monad Maybe where
Nothing >>=_ = Nothing
(Just x) >>= f = f x
return = Just
So that means that it will indeed "unpack" values out of a Just data constructor, but in case a Nothing comes out of it, then this means that the result of the entire do block will be Nothing.
This is more or less the convenience the Monad Maybe offers: you can make computations as a chain of succesful actions, and in case one of these fails, the result will be Nothing, otherwise it will be Just result.
You can thus not at the end return an Int instead of a Maybe Int, since it is definitely possible - from the perspective of the types - that one or more computations can return a Nothing.
You can however "post" process the result of the do block, if you for example add a "default" value that will be used in case one of the computations is Nothing, like:
import Data.Maybe(fromMaybe)
main :: Int -> Int -> Int
main x y = fromMaybe 0 $ do
first <- compute x y
second <- compute (x+2) (y+2)
third <- compute (x+4) (y+4)
return (first + second + third)
Here in case the do-block thus returns a Nothing, we replace it with 0 (you can of course add another value in the fromMaybe :: a -> Maybe a -> a as a value in case the computation "fails").
If you want to return the first element in a list of Maybes that is Just, then you can use asum :: (Foldable t, Alternative f) => t (f a) -> f a, so then you can write your main like:
-- first non-failing computation
import Data.Foldable(asum)
import Data.Maybe(fromMaybe)
main :: Int -> Int -> Int
main x y = fromMaybe 0 $ asum [
compute x y
compute (x+2) (y+2)
compute (x+4) (y+4)
]
Note that the asum can still contain only Nothings, so you still need to do some post-processing.
Willem's answer is basically perfect, but just to really drive the point home, let's think about what would happen if you could write something that allows you to return an int.
So you have the main function with type Int -> Int -> Int, let's assume an implementation of your compute function as follows:
compute :: Int -> Int -> Maybe Int
compute a 0 = Nothing
compute a b = Just (a `div` b)
Now this is basically a safe version of the integer division function div :: Int -> Int -> Int that returns a Nothing if the divisor is 0.
If you could write a main function as you like that returns an Int, you'd be able to write the following:
unsafe :: Int
unsafe = main 10 (-2)
This would make the second <- compute ... fail and return a Nothing but now you have to interpret your Nothing as a number which is not good. It defeats the whole purpose of using Maybe monad which captures failure safely. You can, of course, give a default value to Nothing as Willem described, but that's not always appropriate.
More generally, when you're inside a do block you should just think inside "the box" that is the monad and don't try to escape. In some cases like Maybe you might be able to do unMaybe with something like fromMaybe or maybe functions, but not in general.
I have two interpretations of your question, so to answer both of them:
Sum the Maybe Int values that are Just n to get an Int
To sum Maybe Ints while throwing out Nothing values, you can use sum with Data.Maybe.catMaybes :: [Maybe a] -> [a] to throw out Nothing values from a list:
sum . catMaybes $ [compute x y, compute (x+2) (y+2), compute (x+4) (y+4)]
Get the first Maybe Int value that's Just n as an Int
To get the first non-Nothing value, you can use catMaybes combined with listToMaybe :: [a] -> Maybe a to get Just the first value if there is one or Nothing if there isn't and fromMaybe :: a -> Maybe a -> a to convert Nothing to a default value:
fromMaybe 0 . listToMaybe . catMaybes $ [compute x y, compute (x+2) (y+2), compute (x+4) (y+4)]
If you're guaranteed to have at least one succeed, use head instead:
head . catMaybes $ [compute x y, compute (x+2) (y+2), compute (x+4) (y+4)]

Check and see if all elements of a list match a parameter

I want to make a function that checks to see if each row of the board for the Bert Bos puzzle is red one row at a time, but conceptually I'm having a hard time with this. Initially I make the board with all blue squares, but once the squares have been flipped with a flip function, the allRed function should be able to tell if the row is all red or not. Each row is represented by a list of colors, either Blue or Red
I know I should be using the all function, but I'm having some problems actually writing it out for my situation
Here is what I have so far:
generateboard :: Int -> [[Color]]
generateboard n = replicate n (replicate n Blue)
allRed :: [[Color]] -> Bool
let board = generateboard
allRed board = []
allRed board = all ([x:_ | x <- board, x == Red])
allRed board
There are many mistakes and misunderstandings here. I recommend reading any of the introductory Haskell materials to strengthen your basic understanding of the language. I will answer the question directly nonetheless.
generateboard looks great.
You are right to think all :: Foldable t => (a -> Bool) -> t a -> Bool will help us define allRed. If the type is confusing you can instead think of it as (a -> Bool) -> [a] -> Bool. The documentation says:
Determines whether all elements of the [list] satisfy the predicate.
To use all we need a predicate (a function) with type a -> Bool and a list of type [a]. We know what the predicate needs to be:
\x -> x == Red
Another way to write this is:
(==) Red
The predicate has type Color -> Bool and so our list must then have type [Color]. However, we have a list of type [[Color]]. There are two ways I can see to go about this.
The simpler idea is to observe that the board structure is irrelevant if all we care about is the cells. Therefore, we can flatten the structure with concat :: [[a]] -> [a]. Then our solution is thus:
allRed xs = all ((==) Red) (concat xs)
Which is also written:
allRed = all ((==) Red) . concat
Another solution is to observe that if all rows are red then the whole board must be red. This solution is:
allRed xs = all (all ((==) Red)) xs
Which is also written:
allRed = all (all ((==) Red))
First, the all function:
all :: (a -> Bool) -> [a] -> Bool
all p xs = ...
takes a function p representing a property and a list xs and tests if p x is true (i.e., if x has property p) for every element x of xs. (For example, all even [2,4,7] checks if all elements of the given list are even, and it returns False because even 7 equals False.) So, to use all, you need two arguments -- a list of items to check, and a function that checks one item.
Second, when faced with the problem of processing a data structure in Haskell (in this case [[Color]]), an excellent rule of thumb is to the deconstruct the structure from the outside in, using one function for each level of structure. You have an (outer) list of (inner) lists of colors, so start with the outer list, the list of rows.
How would you write a function that checks if all the rows in the outer list satisfy the property that they "contain only red colors"? Or, to put it more simply, how would you write this function using all if you already had a helper function redRow that expressed the property of a row having only red colors?
redRow :: [Color] -> Bool
redRow row = ...
If you can write allRed board using all, board, and redRow, you'll have reduced the problem to writing the definition of redRow, which operates on a simpler data structure, an (inner) list of colors.
To write redRow, you should likewise be able to use all again with a function expressing the property of a color being red:
isRed :: Color -> Bool
isRed col = ...
(or using an equivalent lambda or "section" directly).
In this case, another approach is possible, too -- you could use concat to "flatten" the outer and inner list together and then tackle the easier problem of checking if all colors in a big long list are red.

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.

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