I am new to Haskell and having problems using recursion to make a deck of cards.
I have all these definitions:
data Suit = Club | Diamond | Heart | Spade
data Value = Two | Three | Four | Five | Six | Seven
| Eight | Nine | Ten | Jack | Queen
| King | Ace
type Card = (Suit, Value)
type Deck = [Card]
instance Show Suit where
show Club = "Club"
show Diamond = "Diamond"
show Heart = "Heart"
show Spade = "Spade"
instance Show Value where
show Two = "Two"
show Three = "Three"
show Four = "Four"
show Five = "Five"
show Six = "Six"
show Seven = "Seven"
show Eight = "Eight"
show Nine = "Nine"
show Ten = "Ten"
show Jack = "Jack"
show Queen = "Queen"
show King = "King"
show Ace = "Ace"
I am trying to write a function
makeDeck :: Deck
which returns a list of cards in the order the Data is given, so (Club, Two - Ace), (Diamond, Two-Ace), etc.
I want to do this using recursion, which is why I am having so much difficulty.
Any help would be greatly appreciated.
Thank you!
This doesn't use recursion, but a more canonical way of doing this is:
Add deriving Enum to the definition of Suit and Value, then:
makeDeck :: Deck
makeDeck = [(suit, value) | suit <- [Club..Spade], value <- [Two..Ace]]
Alternatively, provide fully defined lists of all suits and values rather than using Enum.
Given:
data Suit = Club | Diamond | Heart | Spade deriving (Show, Enum)
data Value = Two | Three | Four | Five | Six | Seven
| Eight | Nine | Ten | Jack | Queen
| King | Ace deriving (Show, Enum)
type Card = (Suit, Value)
type Deck = [Card]
makeDeck :: Deck
there are lots of ways to calculate a Cartesian Product -- the product of sets.
All of the functions used in these examples can be looked up on Hoogle:
Monads
Using do notation:
makeDeck = do
suit <- [Club ..]
value <- [Two ..]
return (suit, value)
The unsugared form of the above, which uses >>=:
makeDeck = [Club ..] >>= \suit ->
[Two ..] >>= \value ->
return (suit, value)
Lifting:
makeDeck = liftM2 (,) [Club ..] [Two ..]
Function application within monads:
makeDeck = return (,) `ap` [Club ..] `ap` [Two ..]
Applicatives
Lifting:
makeDeck = liftA2 (,) [Club ..] [Two ..]
Function application within applicatives:
makeDeck = pure (,) <*> [Club ..] <*> [Two ..]
Which is the same as:
makeDeck = (,) <$> [Club ..] <*> [Two ..]
List comprehensions
See #ivanm's answers.
Without any type classes
makeDeck = concatMap (\suit -> map ((,) suit) [Two ..]) [Club ..]
If you need to use recursion explicitly, you can replace concatMap with its definition, and so on until you get to foldr, where the real recursive action happens.
Firstly, are you aware of list comprehensions and all the awesome things you can do with them? The makeDeck function could be written as a fairly simple list comprehension (as ivanm pointed out in his answer), especially given the order you'd like the deck to be in.
However, if you'd still like to use recursion, there are a few ways to go about it. First, figure out what variables you'll need to keep track of during the whole operation. You'll need to keep the current list of cards, and a record of which suit and value you're at. So the type signature might look something like makeDeck :: Suit -> Value -> Deck. Then you'd want to use pattern matching to handle the several possible cases during the computation, such as
makeDeck suit Ace deck = (suit,Ace):(makeDeck (succ suit) Two)
[...]
As you can see, this might turn out to be a fairly long and unwieldy definition. The list comprehension method would yield a much more short, elegant, and canonical solution. Regardless of which you choose, you'll need to add deriving Enum to the end of your datatype declarations. Read up on the deriving keyword here or elsewhere online if you're not familiar with it.
Others have pointed you towards list comprehensions, but if you would like to write it recursively, read on.
This sounds like homework, so I'll just try and give you tips that point you in the right direction (as opposed to writing it for you).
Thing to realize #1:
If you derive the Enum typeclass for your algebraic data types, you can create enumerations like so:
*Main> [Club .. Spade]
[Club,Diamond,Heart,Spade]
Thing to realize #2:
You can create lists of tuples like that, by using maps. You'll end up with [[Suit]], so you should use the concat function to join them into a Deck.
*Main> concat $ map (\x -> map (\y -> (x, y)) ['a'..'c']) [1..3]
[(1,'a'),(1,'b'),(1,'c'),(2,'a'),(2,'b'),(2,'c'),(3,'a'),(3,'b'),(3,'c')]
Thing to realize #3:
You can implement map recursively. Here's the definition from the Prelude:
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
So you could write the (map . map) as one big recursive function. Good luck!
Related
dobb[] = []
dobb (x:xs) = [x * 2| x<- xs]
I am really new to haskell and started learning it this week. I want to create a function that multiplies each element in a list by 2. So the list would go from [1,2,3] to [2,4,6]. The code I have works fine, except it skips the first element of the list and goes from [1,2,3] to [4,6]. How can I make the code multiply the first element as well?
[x*2 | x<-[1..5]]
I've found this line that does what I am looking for, but I dont understand how to go from this line of code and convert it to a function that works for all lists.
I'll address your last question,
how to go from this line of code,
[x*2 | x <- [1..5]]
and convert it to a function that works for all lists[?]
This is known as generalization and is achieved by abstraction. First we name it,
foo = [x*2 | x <- [1..5]]
then we name that arbitrary piece of data we used as an example to work on,
foo = let {xs = [1..5]} in [x*2 | x <- xs]
and then we abstract over it by removing that arbitrary piece of data in the internal definition, letting it become the function parameter instead, to be specified by this, now, function's callers:
foo xs = [x*2 | x <- xs]
and there it is, the general function working on all lists, doing the same thing as it did on the specific example we used at first.
If you use the pattern (x:xs) then you unpack the list such that x is the head (first item) of the list, and xs is the tail (remaining items) of that list. For a list [1,4,2,5], x will thus refer to 1, and xs to [4,2,5].
In the list comprehension, you then use x <- xs as a generator, and thus you enumerate over the remaining elements. The x in the list comprehension is furthermore not the head of the list, but a more locally scoped variable.
You can work with list comprehension and work on the entire list, so:
dobb :: Num a => [a] -> [a]
dobb xs = [x * 2| x <- xs]
We can also work with map :: (a -> b) -> [a] -> [b] to perform the same operation on the elements:
dobb :: Num a => [a] -> [a]
dobb = map (2*)
How would one return a random value for a data type like below?
datatype rank = Jack | Queen | King | Ace | Num of int
I am working on a function generate a list of random cards for input to another function, so there is also the need for a similar function for suit.
The output should either be a symbol like Jack, King, etc, or an int from 2 to 9.
The code below is incorrect:
fun pick_rank() =
case Random.randRange(2,13) of 13 => Ace
| 12 => King
| 11 => Queen
| 10 => Jacl
| Int v => v
How would one return a random value for a data type like below?
datatype rank = Jack | Queen | King | Ace | Num of int
I have two answers: Either you generate each value uniquely, or you generate all possible values, shuffle them and pick one. If you just want a random variable in isolation, the former is easiest. But if you want to simulate a card game in which drawing the same card twice is not possible, then you probably want the shuffle.
You can see how I made a command-line blackjack game. I'll repeat both approaches here:
(* There are 13 card ranks, 4 suits *)
datatype rank
= Ace | Two | Three | Four | Five | Six | Seven
| Eight | Nine | Ten | Jack | Queen | King
datatype suit = Hearts | Clubs | Diamonds | Spades
datatype card = Card of suit * rank
fun concatMap f xs = List.concat (List.map f xs)
fun product xs ys = concatMap (fn x => map (fn y => (x,y)) ys) xs
val allCards = map Card
(product
[Hearts,Clubs,Diamonds,Spades]
[Ace,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack,Queen,King])
(* Create a new pseudo-random number generator, prng *)
val prng = Random.newgen ()
(* rlist determines a random index in [0 ; length xs[. *)
fun rlist xs = Random.range (0, length xs) prng
(* remove removes the n'th element of a list *)
fun remove (_, []) = raise Domain
| remove (0, card::library) = library
| remove (n, card::library) = card::remove (n-1, library);
(* randomtake removes and returns the i'th (random) element of a list *)
fun randomtake library =
let val i = rlist library
val card = List.nth (library, i)
val rest = remove (i, library)
in
(card, rest)
end
(* Shuffling is done by removing random cards until there are no cards left *)
fun shuffle [] = []
| shuffle cards =
let val (c,r) = randomtake cards
in
c :: shuffle r
end
Using these functions, you could pick a single random card by doing randomtake allCards, or you could pick any amount of random cards without picking the same card by first shuffle allCards and pick the top elements.
Note that these are not efficient methods. As an exercise, you could implement the Fisher-Yates shuffle.
I want to return a sequence of Cards in a game in Haskell. For example:
[(SIX,D),(SEVEN,D),(EIGHT,S)] ~> [(SIX,D),(SEVEN,D)]
[(SIX,D),(SEVEN,S)] ~> []
[(SIX,D),(SEVEN,D)] ~> [(SIX,D),(SEVEN,D)]
Until now, I have this function:
findSeq :: [Card] -> [Card]
findSeq [] = []
findSeq (h:t)
| null t = [h]
| Just h == (pCard (head t) pack) = h:findSeq t
| otherwise = [h]
Which returns even the first card: i.e, unsuitable for example 2 above. How can I return a sequence, or nothing else if there is no sequence of consecutive elements in there?
I also tried filtering them, but I received 'too many arguments exception'. Any help?
This is how I would do it:
import Data.List (groupBy)
import Data.Function (on)
data Suit = Clubs | Diamonds | Hearts | Spades deriving Eq
data Face = Ace | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten
| Jack | Queen | King deriving Enum
type Card = (Face, Suit)
findSequences :: [Card] -> [[Card]]
findSequences = [sequence | sequence <- groupBy ((==) `on` snd),
contiguous (map fst sequence),
length sequence > 1]
contiguous :: Enum a => [a] -> Bool
contiguous (x:xs) = map fromEnum xs == take (length xs) [fromEnum x + 1 ..]
The findSequences function finds all the sequences in the deck (except single card sequences).
Well, mathematically it actually makes perfect sense to consider a single card a sequence of one card. So it's a good idea to not change that behaviour as such... just extend the definition so you can obtain the real desired result from that.
The real problem is not that you get single cards as single-element sequences, but that you don't get anything behind them. To fix that, you need to first obtain not merely the first, but all sequences in the list:
findSeqs :: [Card] -> [[Card]]
findSeqs [] = []
findSeqs [h] = [[h]]
findSeqs (h:t#(h':_)) -- avoid `head` and `null`... pattern matching FTW!
| Just h == (pCard h' pack) = h ^: findSeqs t
| otherwise = [h] : findSeqs t
I've used the helper
(^:) :: a -> [[a]] -> [[a]]
h ^: (hl:ls) = (h:hl) : ls
_ ^: [] = []
Once you have findSeqs, you merely need to skim the result for the first non-degenerate sequence.
type a = [(Int,Int,Int,Int)]
fun:: a -> Int
func [a,b,c,d] = ?
I have a list of tuples like this what i required is to apply list comprehensions or pattern matching .. example taking sum or filter only divide 2 numbers ... i just want a start how to access values and or a list comprehension to this List of Tuples
To sum up the as, use something like this:
type A = [(Int, Int, Int, Int)]
func :: A -> Int
func tuples = sum [a | (a, b, c, d) <- tuples]
Also note that a type alias must begin with an upper case letter. Lower case letters are used for type variables.
hammar's answer covered list comprehensions, the basic schema for recursive functions using pattern matching is:
f [] = ..
f ((a,b,c,d):xs) = ..
So you need to specify a base case for a list containing no 4-tuples, and a recursive case for when the list consists of a 4-tuple (a,b,c,d) followed by a (possibly empty, possibly non-empty) list of 4-tuples xs. The pattern on the second line is a nested pattern: it first matches the list against a pattern like (x:xs), i.e. element x followed by rest of list xs; and then it matches x against the 4-tuple structure.
Below, I'll give some basic examples. Note that you can also write this with standard higher-order functions, such as filter and map, and I'm deliberaty not mentioning things like #-patterns and strictness. I do not recommend doing it like this, but it's just to give you an idea!
When you want to sum the first part of the tuples, you could do it like this:
sum4 :: [(Int,Int,Int,Int)] -> Int
sum4 [] = 0
sum4 ((a,b,c,d):xs) = a + sum4 xs
If you want to filter out the tuples where all of a,b,c and d are even:
filter4allEven :: [(Int,Int,Int,Int)] -> [(Int,Int,Int,Int)]
filter4allEven [] = []
filter4allEven ((a,b,c,d):xs)
| all even [a,b,c,d] = (a,b,c,d) : filter4AllEven xs
| otherwise = filter4AllEven xs
(If the use of all confuses you, just read even a && even b && even c && even d)
And finally, here's a function that returns all the even tuple components (tuples themselves can't be even!) in the same order as they appear in the argument list:
evenTupleComponents :: [(Int,Int,Int,Int)] -> [Int]
evenTupleComponents [] = []
evenTupleComponents ((a,b,c,d):xs) = [x | x <- [a,b,c,d], even x] ++ evenTupleComponents
Once you do a couple of exercises like these, you'll see why using standard functions is a good idea, since they all follow similar patterns, like applying a function to each tuple separately, including or excluding a tuple when it has some property or, more generally, giving a base value for the empty list and a combining function for the recursive case. For instance, I would write evenTupleComponents as evenTupleComponents = filter even . concatMap (\(a,b,c,d) -> [a,b,c,d]), but that's a different story :)
Problem
i have list of int as [123,123] which i required to be as [1,2,3,1,2,3]
Current Code
i tried out the following code using recursion
fat::[Int]->[Int]
fat [] = []
fat (a,b,c:xs) = a : b : c : fat xs
Conclusions
i have no idea how to acess values as '1' , '2 , '3 in a list [123,123] separetly
I suggest to use the digs function given in this answer on each element of your list. It splits an Int into a list of digits ([Int]). Then you just need to concatenate the resulting lists. This 'map and concatenate results' requirement is a perfect job for concatMap
fat :: [Int] -> [Int]
fat = concatMap digs
This gives:
*Main> fat [123,123]
[1,2,3,1,2,3]
Which is what you want, if I understood correctly.
splitNum :: Int -> [Int]
splitNum n | n <= 9 = [n]
| otherwise = (splitNum (n `div` 10)) ++ [n `mod` 10]
fat :: [Int] -> [Int]
fat x = concatMap splitNum x
splitNum is used to convert an Int to a [Int] by splitting it into the division by ten reminders and appending the resulting Int to the splitted rest (recursion!)
Now, having a function that converts numbers into lists, go through input, apply splitNum to any Number in the inner list and concat all resulting lists (list comprehension!)
As a new Haskell programmer I will give you my thoughts of this problem. Just because I think it's good to have many alternatives, especially from different people with different experience.
Here's my take on the problem:
For each item in the list, convert that item to a char list using read.
Send that char list into a function which converts each item of that list into an int, then return an list of ints.
Concat that list of ints into the main list.
To clarify:
[123, 234]
123 turns into ['1', '2', '3']
['1', '2', '3'] turns into [1, 2, 3]
[1, 2, 3] gets concat in the main list
the cycle repeats for 234.
The util function would look something like this:
import Char
charsToInts :: [Char] -> [Int]
charsToInts [] = []
charsToInts (x:xs) = digitToInt x : charsToInts xs
Coming from a imperative background that's how I would have solved it. Probably slower than just splitting the number mathematically, but I thought it would be interesting to show a alternative.
To pinpoint the problem bluntly, you have no idea how to access the digits separately because you do not understand Haskell types and pattern matching. Let me try to help dispel some of your misconceptions.
Let's look at your list:
[123, 123]
What is its type? It is clearly a list of ints, or [Int]. With lists, you can pattern match on the constructor :, known to lispers as "cons", or "list constructor". You put a single element on the left side of the :, and another list on the right side. The list on the right side can be the empty list [], which basically indicates the end of the list. Haskell provides "syntactic sugar" to make lists easier to write, but [123,456] actually gets desugared into 123:(456:[]). So when you pattern match (x:y:z), you can now see that x will be assigned 123 and y will be assigned 456. z will be the rest of the list after x and y; in this case only [] is left.
Now then, pattern matching with : works for lists. Ints are not lists, so you can't use : to pattern match on the digits of an Int. However, Strings are lists, because String is the same as [Char]. So if you turn your Int into a String then you can pattern match on each character.
map show [123, 123]
map applies a function to all elements of a list. show can take an Int and turn it into a String. So we map show over the list of Ints to get a list of Strings.
["123", "123"]
Now let's turn those Strings into lists of Ints. Since String is simply [Char], we will again make use of map.
map digitToInt "123" -- this requires that you import Data.Char (digitToInt)
This will give us [1,2,3]; each Char in the list is turned into an Int. This is what we want to do to each String in our list ["123", "123"]. We want to map digitToInt to each String. But we have a list of Strings. So what do we do? We map it!
map (map digitToInt) ["123", "123"]
This will give us [[1,2,3], [1,2,3]]. Almost what we wanted. Now we just have to flatten the list of list of Ints ([[Int]]) into just a list of Int ([Int]). How can we do that? Stop...Hoogle time! Hoogling [[a]] -> [a] we find the very first hit, concat, is exactly what we wanted.
Let's put it all together. First we do map show to get from [Int] to [String]. Then we do map (map digitToInt) to get from [String] to [[Int]]. Then we do concat to get from [[Int]] to [Int]. Then we'll just print it out!
import Data.Char (digitToInt)
main = print $ concat $ map (map digitToInt) $ map show $ [123, 123]
Now let's pull most of that out into a function fat
import Data.Char (digitToInt)
main = print $ fat [123, 123]
fat :: [Int] -> [Int]
fat xs = concat $ map (map digitToInt) $ map show $ xs
From here you could make it prettier in a few different ways. concat $ map is the same as concatMap, and since we map both (map digitToInt) and show in sequence, we can merge those. Also making it pointfree, we can end up with quite a terse definition:
fat = concatMap (map digitToInt . show)
For the sake of completeness, I wrote it as suggested by #Ancide
Implementation
fat' :: [Int] -> [Int]
fat' l = map (read) [[z] | z <- [x | k <- (map (show) l), x <- k]]
Explanation:
{- last result -} stands for the result of the last code explained.
map (show) l
This takes every element inside l and converts it to [String].
[x | k <- {- last result -}, x <- k]
While k goes through all elements inside the last result, x enumerates all character in each k. All those are added to a list. Now you have a String, respectively a [Char] with all digits next to each others.
[[z] | z <- {- last result -}]
This part takes each Char from the String and puts it into an empty String. Notice the [z] part! This make a list around z, which is (see above) the same as String. Now you have a list of String with a String for each digit.
map (read) {- last result -}
This takes every item in the last result and converts it back to Int and joins them to [Int]. Now you have a list of type [Int] of the wanted result.
Resumé
Although this implementation is possible, it's neither fast, due to all the type conversions, nor readable.
Playing around with the list monad I came up with this. Pretty much the same #Ankur's solution, except using the list monad:
fat :: [Int] -> [Int]
fat is = is >>= show >>= return . digitToInt
If you had two numbers, a and b then you could turn them into a single number by doing 10*a + b. The same principles apply for three.
It sounds like one way of doing this would be to splitEvery into lumps of three and then map a function to turn a list of three into a single number.
Does that help?
You need a function to convert Integer to string... which is obviously Show function
Another function to convert a Char to Integer which is "digitToInt" in module Char
And here we go :
fat::[Int]->[Int]
fat [] = []
fat ls = concat $ map (map digitToInt) (map show ls)
Please let me know if it works :)