How to use a global variable within a function in Haskell - haskell

In section Incorrectly matching against a variable from chapter 3 of real world haskell, there is an example as follows:
-- file: ch03/BogusPattern.hs
data Fruit = Apple | Orange
apple = "apple"
orange = "orange"
whichFruit :: String -> Fruit
whichFruit f = case f of
apple -> Apple
orange -> Orange
The explanation says in case f of part, apple and orange are not treated as global variables as defined before the function declaration. They are local variables.I thought if there is no local variable owning the same name as a global variable, the global variable is not hidden.

The main thing here is that variables in pattern matches always introduce new variables instead of referring to existing ones. Your problem has nothing to do with global vs local variables.
If you want to match the value of f to the value of some variable like apple in a pattern you need to use pattern guards and equality tests. E.g.
whichFruit f
| f == apple = Apple
| f == orange = Orange

You have hit upon irrefutable patterns. As the book mentions, plain variable names and the wild card _ are examples of irrefutable patterns. Another example which will demonstrate irrefutable patterns more clearly:
data Fruit = Apple | Orange deriving (Show)
patternMatch f = case f of
something -> Apple
Now the above program typechecks with an warning. In ghci:
ghci> patternMatch 2
Apple
ghci> patternMatch "hi"
Apple
So basically the variable something is an irrefutable pattern which matches anything.
Now,coming back to your example:
whichFruit :: String -> Fruit
whichFruit f = case f of
apple -> Apple
orange -> Orange
Here the variable apple and orange are irrefutable patterns. They doesn't refer to the global function which you have already created. In fact you can remove the global definition of apple and orange and compile them in order to get an idea. Whatever input you give, you will always get Apple as an answer for the above code (since it is an irrefutable pattern):
ghci > whichFruit "apple"
Apple
ghci > whichFruit "orange"
Apple
ghci > whichFruit "pineApple"
Apple
How to use a global variable within a function in Haskell ?
That's pretty easy actually. Just use them in your function definition.
data Fruit = Apple | Orange deriving (Show)
apple = "apple"
orange = "orange"
giveFruit :: Fruit -> String
giveFruit Apple = apple
giveFruit Orange = orange
In ghci:
ghci> giveFruit Apple
"apple"
ghci> giveFruit Orange
"orange"
Using the variable in the function definition is straight forward.
What should be done if I want the variable to refer to a global
variable owning the same name?
One way would be to use the entire module name to refer to it. Example:
module Fruit where
data Fruit = Apple | Orange deriving (Show)
apple = "apple"
orange = "orange"
giveFruit2 :: Fruit -> String
giveFruit2 apple = Fruit.apple

Right. But there is a local variable apple here owning the same name as the global variable apple, namely apple (duh).
The crucial thing about patterns is that they don't so much compare variables as look out for specific distinguishing features, while simultaneously re-packaging all other information into new variables. The "distinguishing features" are constructor matches (always uppercase1), which don't appear in case f of { apple -> ... }, so simply all the information is passed on in the variable apple.
A more idiomatic example
data Vegetable = Tomato | Potato
data Edible = Fruit Fruit | Vegetable Vegetable
If you want a function to take an Edible argument, it's often useful to deconstruct the type. This might look thus:
canJuice :: Edible -> Bool
canJuice (Fruit Apple) = False
canJuice (Fruit Orange) = True
canJuice (Vegetable Tomato) = True
canJuice (Vegetable Potato) = False
Now, for more complicated data it's awkward to write such lots of canJuice clauses. An alternative would be to first match only on the outmost constructor, and delegate the further work elsewhere:
canJuice :: Edible -> Bool
canJuice (Fruit fruit) = fruitJuicy fruit
canJuice (Vegetable veg) = vegetableJuicy veg
vegetableJuicy :: Vegetable -> Bool
vegetableJuicy Tomato = True
vegetableJuicy Potato = False
For this to work, we needed Haskell's feature of treating any lowercase name appearing in a pattern as a new variable, which takes on the value in the "hole" of our pattern match.
1 There are also infix constructors, the best-known is list-cons (:) (they all start with a colon, like all named constructors start uppercase).

Related

Haskell: Value Function

I'm still doing the exercise from the book and the one exercise says that I should create a function: value :: Hand -> Int, which returns the value of the hand.
My code so far looks like this:
data Hand = PairOf Rank | ThreeOf1 Rank | ThreeOf2 Suit
value: Hand -> Int
otherwise = 0
--
I now have another problem, because I don't know how to describe "Nothing".
Nothing is described here as a possible hand combination in which Pair, ThreeOf1 and ThreeOf2 do not occur.
Would otherwise = 0 work or doesn't that make much sense?
Thanks again for the suggestions, I corrected them! Thanks also in advance for explanations and help.
otherwise won't work here. What you want is an irrefutable pattern that will match anything, and further since you don't care what gets matched, you specifically want the pattern _:
value :: Hand -> Int
value (PairOf r1) = 1
value (ThreeOf r1) = 2
value (Flush s1) = 3
value _ = 0
Since you don't care about what kind of pair, etc you get, you can also use _ in the other cases:
value :: Hand -> Int
value (PairOf _) = 1
value (ThreeOf _) = 2
value (Flush _) = 3
value _ = 0
If you wanted to match Nothing (or whatever name you come up with that doesn't conflict with the Maybe constructor) specifically, it's just
value Nothing = 0
One of the problems you might be having is that there is no Nothing.
Here's the full type of Hands for holdem:
data HandRank
= HighCard Rank Rank Rank Rank Rank
| OnePair Rank Rank Rank Rank
| TwoPair Rank Rank Rank
| ThreeOfAKind Rank Rank Rank
| Straight Rank
| Flush Rank Rank Rank Rank Rank
| FullHouse Rank Rank
| FourOfAKind Rank Rank
| StraightFlush Rank
deriving (Eq, Ord, Show, Generic)
The extra ranks in the data type are there to distinguish hands, so a pair of aces with a King & Queen kicker beats a pair of aces with a King & Jack kicker. But otherwise, it's the same as your setup.
Once you have a complete transformation from a set of cards to a hand value, there is no nothing. What you might be thinking of as nothing is the HighHand line in the sum type. If your context is that's it for possible hands, then I would add a NoValue to the Hand sum type, as better than outputting a Maybe Hand.
Using the wild cards otherwise _ or value _ introduces a chance of a bug because you might forget about coding up a full house, say, and your existing function would work. If you forget to code one of the sum types, and you don't have a match-any pattern, the compiler will complain. Providing the compiler with all branches of a sum type is also a hot development area of GHC, and it will be fast.

Is there something like DuplicateRecordFields for constructors in Haskell? [duplicate]

i am new to Haskell and probably missing something really basic here, but i am not able to re-use same value constructor among different data types.
data Colour = Red | Pink | Orange | Yellow
data Fruit = Apple | Orange | Banana
This produces error saying
Multiple declarations of ‘Orange’
Not sure why this isn't allowed, i have been using OCaml before learning Haskell and was able to define types like this
As a quick exercise try just defining one of your data types and then opening up GHCi to inspect it.
data Colour = Red | Pink | Orange | Yellow
If you use :t in GHCi, it will tell you the type of anything.
> :t Red
Red :: Colour
> :t Orange
Orange :: Colour
So this tells you that your data constructor Orange is really just a function that takes no arguments and produces a value of type Colour.
So what happens if you add a duplicate declaration?
data Colour = Red | Pink | Orange | Yellow
data Fruit = Apple | Orange | Banana
Now you have defined a function Orange that takes no arguments and produces a value of type Colour or a value of type Fruit. This won't work at all! It would be the same as defining your own custom function foo and giving it multiple type signatures:
foo :: Int
foo :: String
foo = "6"
Which obviously doesn't work either.
To get around this, you can define each data type in its own module, and use a qualified import to scope them correctly:
import qualified Colour as C -- Module Colour.hs
import qualified Fruit as F -- Module Fruit.hs
orange1 = C.Orange :: C.Colour
orange2 = F.Orange :: F.Fruit
Now, you might be thinking "The compiler is smart, it should know what Orange I'm talking about when I'm using it." and you'd be partially right. There is an ongoing effort to bring Overloaded or Duplicate record fields into Haskell. There are various other questions of that ilk already defined here, but I'll list a few
references for further reading.
Why DuplicateRecordFields cannot have type inference?
https://github.com/adamgundry/ghc-proposals/blob/overloaded-record-fields/proposals/0000-overloaded-record-fields.rst
https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/DuplicateRecordFields
There is no particular reason, that is how language was designed. I think the idea was to make sure compiler can infer type for as many expressions as possible. Note that if language will allow to reuse constructors, then you'll have to specify type for show Orange expression - compiler can't infer it anymore. Though now a lot of people don't take this reason seriously, and a lot of modern language extentions do break compiler's ability to infer types for many expressions. So I guess in few years you'll find that your example works already :)

How to merge two hands of cards together in Haskell?

I'm still very new to Haskell, and I'm curious as to how I would merge two Hand's together, so that, the first hand is placed on top of the second hand. I want it to be an infix operator, namely (<+). Here's some code to assist you. I keep getting an error saying "The type signature for ‘<+’ lacks an accompanying binding".
data Rank = Numeric Integer | Jack | Queen | King | Ace
data Suit = Hearts | Spades | Diamonds | Clubs
data Card = Card Rank Suit
data Hand = Empty | Add Card Hand
(<+) :: Hand -> Hand -> Hand
h1 (<+) h2 = undefined
Many thanks in advance for any advice given.
The definition should either be
h1 <+ h2 = undefined
or
(<+) h1 h2 = undefined
You are currently trying to use a function name as an infix operator.

How to write "Show" Typeclass for data

I have a very simple data and I want to use Show Typeclass to give it a nice output.
data Fruit = Apple | Orange Int
instance Show Fruit
where
show Apple = "Hey Apple"
show Orange a = "X number of Orange"
This gives the following error but I don't know how to fix it:
Equations for `show' have different numbers of arguments
You just forgot some parens :)
instance Show Fruit where
show Apple = "Hey Apple"
show (Orange a) = show a ++ " number of Orange"
Patterns like Orange a need parens to disambiguate from something like Apple a where we really have two arguments.

Function with parameters in Haskell

I'm trying to write a few functions that have parameters in haskell.
For example: I make a list with all kinds of colors, but I want the function to only get the color orange from the list, how do I specify this in the function?
getColor :: a -> a
getColor = orange
You want a function that takes a list of many colours and returns a single colour (presumably of your choosing). You should start with a data type to represent your colours.
data Colour = Red | Orange | Yellow | Green | Blue
now you want a function getColour with the type
getColour :: Colour -> [Colour] -> Colour
which takes a Colour and a list of Colour and picks out the desired colour from the list. However, lists can be empty, or the list might not contain the colour you want! What will getColour return in that case?
In Haskell we handle a function that may not return a result using Maybe. The new type of getColour is
getColour :: Colour -> [Colour] -> Maybe Colour
which means getColour will either return Nothing, or Just colour where colour is from the list.
Lastly, I'll mention that there are a few ways you could actually write the body of getColour, using pattern matching and explicit recursion, or with standard library functions from Haskell's Prelude. I assume you're new to Haskell, so I'd recommend the former. Here's some code to get you started:
getColour _ [] = Nothing
getColour colour (x:xs) = ...
Is this enough to help you write getColour by yourself?

Resources