0
votes

I keep getting a Couldn't match expected type Card with actual type [Card] in the first argument of getnumfrmcard (xs) and second argument of (<) namely getnumfrmcard(xs) in the function straight(checks to see if a hand of a cards is a straight)

enter code here
  data Card = Cards (Suit,Face) deriving (Eq)
  data Hand=  Hands[Card]

   straight:: Hand->Bool
   straight (Hands [] )                                     =True
   straight (Hands (x:xs) )                
            | null(xs)==True                          = True
            | getnumfrmcard (x)  < getnumfrmcard (xs) =straight (Hands xs)
            | otherwise                               = False
3

3 Answers

4
votes

This error indicates that the function getnumfrmcard expects an argument of type Card but is given a [Card] (a list of cards). The culprit is the second to last line where you have getnumfrmcard (xs). If you match a list against (x:xs) then x becomes the head of the list (a single element) and xs becomes the tail, which is a list. so in

f []     = []
f (x:xs) = xs

f [1,2,3] -- [2,3]

xs is bound to [2,3].

You could match against (Hands (x0:x1:xs)) but then you need to decide how to deal with a list that only has one argument (I haven't thought about what you're trying to do really).

Also note: You usually don't need parenthesis around function arguments in Haskell, so instead of getnumfrmcard (xs) you want to write getnumfrmcard xs.

1
votes

Also, if you want to check whether or not you have a straight, it is not enough to check whether each card is lower than the next, it has to be one lower.

A more Haskell-y solution comes to mind :

straight (Hands cards) = and $ zipWith nextStraight cards (tail cards)
   where nextStraight c c' = getnumfrmcard c' == getnumfrmcard c+1

zipWith nextStraight cards (tail cards) will combine every pair of adjacent elements in cards by the function nextStraight (a function that checks if two cards are of adjacent values). Then we combine the resulting boolean list by requiring that all pairs must verify the predicate (hence the and function).

Of course, the hand must be sorted beforehand in order for this method to work, otherwise some straights won't be detected ([2H,3D,5S,4D,6C], for example).

0
votes

Coding in haskell is not that obvious, I would put more code into your question so you will not end up with more questions :) So the answer based on Paul answer could look like this i think.

module Test where

data Card = Cards (Int, Int) deriving (Eq, Ord)
data Hand = Hands [Card]

straight :: Hand -> Bool
straight (Hands [] ) = True
straight (Hands [x0] ) = True
straight (Hands (x0:x1:xs) )
    | null(xs) == True = True
    | x0 < x1 = straight (Hands xs)
    | otherwise = False

main :: IO ()
main = print $ straight $ Hands [Cards (5,1), Cards(4,4)]

Feel free to edit this