Issues with QuickCheck involving a data type with a function as a constructor - haskell

wrote the code below and am getting some issues with it :
The error I am getting is : Data constructor not in scope: Int :: Int
If I eradicate the Numeric Int element from my array the code works perfectly fine, however Numeric Int is a constructor of the type Rank so it should also be included but I am unsure of how to include it without this error being produced.
Below is the code and apologises if this question is long-winded or silly, this is my first post on StackOverflow so any feedback on how this q was asked would also be greatly appreciated.
Any help would be immensely appreciated
import Test.QuickCheck
import Data.Data
import Data.Typeable
data Suit = Spades | Hearts | Clubs | Diamonds
deriving Show
data Colour = Black | Red
deriving Show
colour :: Suit -> Colour
colour Spades = Black
colour Hearts = Red
colour Diamonds = Red
colour Clubs = Black
data Rank = Numeric Int | Jack | Queen | King | Ace
deriving Show
rankBeats :: Rank -> Rank -> Bool
rankBeats _ Ace = False
rankBeats Ace _ = True
rankBeats _ King = False
rankBeats King _ = True
rankBeats _ Queen = False
rankBeats Queen _ = True
rankBeats _ Jack = False
rankBeats Jack _ = True
rankBeats (Numeric m) (Numeric n) = m > n
prop_rankBeats :: Rank -> Rank -> Bool
prop_rankBeats a b = rankBeats a b || rankBeats b a
instance Arbitrary Rank where
arbitrary = elements [Numeric Int,Jack, Queen, King, Ace]

Your Arbitrary instance for a Rank contains an Int:
instance Arbitrary Rank where
-- an Int ↓
arbitrary = elements [Numeric Int, Jack, Queen, King, Ace]
But an Int is not a data constructor, but a type constructor. You can not use this.
What you can do is make a generator that looks like:
instance Arbitrary Rank where
arbitrary = oneof ((Numeric <$> arbitrary) : map pure [Jack, Queen, King, Ace])
here the first item Numeric <$> arbitrary will use the Arbitrary instance of the Int type, and furthermore we use map pure [Jack, Queen, King, Ace] to transform these Ranks into Gen Ranks. The oneof :: [Gen a] -> Gen a will then each time pick a random generator from the list. oneof will pick the items with equal weight. We can for example use frequency to pick these with different weights:
{-# LANGUAGE TupleSections #-}
instance Arbitrary Rank where
arbitrary = frequency ((9, Numeric <$> chooseInt (2,10)) : map ((1,) . pure) [Jack, Queen, King, Ace])
here this is more fair: 9 out of 13 times, it will pick a Numeric, and we use chooseInt (2, 10) such that we only generate Ints between 2 and 10.

The code from Willem can also be generically derived.
Using the package generic-random:
{-# Language DataKinds #-}
{-# Language DeriveGeneric #-}
{-# Language DerivingVia #-}
import GHC.Generics
import Generic.Random.DerivingVia
import Test.QuickCheck
-- ghci> :set -XTypeApplications
-- ghci> sample #Rank arbitrary
-- King
-- Queen
-- King
-- Jack
-- Numeric (-4)
-- Numeric (-9)
-- Jack
-- Jack
-- Queen
-- Ace
-- Queen
data Rank = Numeric Int | Jack | Queen | King | Ace
deriving
stock (Show, Generic)
deriving Arbitrary
via GenericArbitraryU Rank
Adding weights (like frequency):
-- ghci> sample #Rank arbitrary
-- Numeric 0
-- Queen
-- Numeric (-4)
-- Numeric (-6)
-- Numeric 4
-- Numeric 3
-- Numeric 9
-- Numeric (-3)
-- Numeric 12
-- Jack
-- Numeric 20
data Rank = Numeric Int | Jack | Queen | King | Ace
deriving
stock (Show, Generic)
deriving Arbitrary
via GenericArbitrary '[9, 1, 1, 1, 1] Rank
We can even implement the choose (2, 10) with generic-override!
{-# Language InstanceSigs #-}
{-# Language ScopedTypeVariables #-}
{-# Language StandaloneKindSignatures #-}
{-# Language TypeApplications #-}
{-# Language TypeOperators #-}
..
import Data.Kind
import Data.Proxy
import GHC.TypeLits
import System.Random
-- ghci> sample #Rank arbitrary
-- King
-- Numeric 10
-- Queen
-- Jack
-- Jack
-- King
-- Numeric 8
-- Numeric 7
-- Numeric 4
-- Numeric 4
-- Numeric 6
data Rank = Numeric Int | Jack | Queen | King | Ace
deriving
stock (Show, Generic)
deriving Arbitrary
via GenericArbitrary '[9, 1, 1, 1, 1]
(Override Rank '[Int `With` Choose 2 10])
Using
type Choose :: Nat -> Nat -> Type -> Type
newtype Choose n m a = Choose a
instance (KnownNat n, KnownNat m, Num a, Random a) => Arbitrary (Choose n m a) where
arbitrary :: Gen (Choose n m a)
arbitrary = Choose <$> choose (fromInteger (natVal #n Proxy), fromInteger (natVal #m Proxy))

Related

Haskell instance function

I'm solving some exercises from a book and now I'm having some difficulties:
In this exercise I shall implement Card as an instance of the class Ord.
But I don't know how exactly I could implement it, so I would appreciate any help.
My code so far looks like this:
data Suit = Diamond | Club | Spade | Heart
data Rank = Seven | Eight | Nine | Ten | Jack | Queen | King | Ace
data Card = Card Suit Rank
instance Ord Card where
....
Now I don't know how exactly to implement this and I would very much like to understand it.
Thanks in advance for the explanations.
We can ask GHCi for information about Ord.
:info Ord
This shows the class definition, followed by a list of instances.
type Ord :: * -> Constraint
class Eq a => Ord a where
compare :: a -> a -> Ordering
(<) :: a -> a -> Bool
(<=) :: a -> a -> Bool
(>) :: a -> a -> Bool
(>=) :: a -> a -> Bool
max :: a -> a -> a
min :: a -> a -> a
{-# MINIMAL compare | (<=) #-}
-- Defined in ‘GHC.Classes’
Its superclass is Eq, and :info Eq tells us:
type Eq :: * -> Constraint
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
{-# MINIMAL (==) | (/=) #-}
-- Defined in ‘GHC.Classes’
So in order to implement Ord for Card, we need two things:
An instance Ord Card, with a definition of compare or (<=)
An instance Eq Card with a definition of (==) or (/=)
Since these instances are very mechanical to write, normally we ask the compiler to derive them automatically:
data Suit = Diamond | Heart | Spade | Club
deriving (Eq, Ord)
data Rank = Seven | Eight | Nine | Ten | Jack | Queen | King | Ace
deriving (Eq, Ord)
data Card = Card Suit Rank
deriving (Eq, Ord)
If you pass the -ddump-deriv flag to GHC, or use :set -ddump-deriv in GHCi, it will print out the code that it generates for these instances.
However, the task is to understand how to implement these instances by hand, so let’s go through it step by step.
We’ll start with Eq. For Suit and Rank, we need to specify that each constructor is equal to itself (a.k.a. reflexivity) and all other constructors are unequal.
instance Eq Suit where
Diamond == Diamond = True
Heart == Heart = True
Spade == Spade = True
Club == Club = True
_ == _ = False
instance Eq Rank where
Seven == Seven = True
Eight == Eight = True
Nine == Nine = True
Ten == Ten = True
Jack == Jack = True
Queen == Queen = True
King == King = True
Ace == Ace = True
_ == _ = False
With that out of the way, we can define == for Card in a similar way, by pattern-matching on values of the form Card suit rank.
instance Eq Card where
-- Two cards are equal if…
Card suit1 rank1 == Card suit2 rank2
-- …their suits are equal,
-- and their ranks are equal.
= …
There are two conventional ways to define the body. One is spelling it out literally: suit1 == suit2 && rank1 == rank2. Another is to use tuples: (suit1, rank1) == (suit2, rank2).
Again, to define Ord, we can begin with the instances for the enumerations Suit and Rank. We have two choices of how to specify these: (<=) or compare. The direct option is to just list out the table of possible cases, abbreviating cases where we can:
instance Ord Suit where
Diamond <= _ = True
Heart <= Diamond = False
Heart <= _ = True
Spade <= Diamond = False
Spade <= Heart = False
Spade <= _ = True
Club <= Club = True
Club <= _ = False
instance Ord Rank where
…
For Card, we now just need to follow the same basic form as for Eq. Since we defined (<=) for Suit and Rank, note that we automatically get a default implementation of the other comparison functions like compare and (<) for those types.
instance Ord Card where
-- Two cards are in order if…
Card suit1 rank1 <= Card suit2 rank2
-- …one rank is less than the other,
-- or their ranks are equal and suits are in order.
= …
Again you can translate this comment verbatim using (<), (||), (==), (&&), (<=).
Try implementing these instances based on compare instead of (<=). Hint: use comparing and instance Monoid Ordering from Data.Ord.
Add deriving (Enum) to Rank and Suit—try using fromEnum to simplify their Eq and Ord definitions.
I can't imagine the exercise actually wanted you to manually write the necessary instances. Especially for Suit and Rank, they would be very tedious (and error prone) to write.
Instead, you probably want to use the deriving keyword to automatically derive the necessary instances. If you write:
data Suit = Diamond | Heart | Spade | Club
deriving (Eq, Ord)
this automatically derives Eq and Ord instances. (The Eq instance is required by the Ord instance.) The derived Eq instance is self-explanatory, and the derived Ord instance uses the order in which the constructors appear in the declaration, so Diamond is the smallest and Club is the biggest. If you want bridge order, use:
data Suit = Club | Diamond | Heart | Spade
deriving (Eq, Ord)
instead. Similarly,
data Rank = Seven | Eight | Nine | Ten | Jack | Queen | King | Ace
deriving (Eq, Ord)
orders the rank from Seven (smallest) to Ace (largest). Then, if you write:
data Card = Card Rank Suit
deriving (Eq, Ord)
the derived instance sorts Cards according to the first field Rank, with ties broken by Suit. If you wrote:
data Card = Card Suit Rank
deriving (Eq, Ord)
it would instead order them by Suit, then Rank.
Some code to illustrate:
data Suit = Diamond | Heart | Spade | Club
deriving (Eq, Ord)
data Rank = Seven | Eight | Nine | Ten | Jack | Queen | King | Ace
deriving (Eq, Ord)
data Card = Card Rank Suit
deriving (Eq, Ord)
main = do
let heart8 = Card Eight Heart
spade8 = Card Eight Spade
diamond7 = Card Seven Diamond
print $ heart8 == heart8 -- True
print $ heart8 == spade8 -- False
print $ heart8 < spade8 -- True
print $ diamond7 < spade8 -- True

Using choose in frequency Haskell QuickCheck

So I have the code below and I am trying to make it an instance of Arbitrary:
data MyData = I Int | B Bool
instance Arbitrary MyData where
arbitrary = do {
frequency [(1, return (I 1)),
(1, return (choose((B True), (B False))))]
}
With this however I get (understandable) the error:
Couldn't match type ‘Gen MyData’ with ‘MyData’
Expected type: Gen MyData
Actual type: Gen (Gen MyData)
How can I accomplish to implement this? Also instead of (I 1) I would like to return I with a random Int. However using the arbitrary function instead of 1 leads to the same error.
Since you seem to want to distribute evenly between I and B constructors, a simpler solution would be to use oneof instead of frequency:
data MyData = I Int | B Bool deriving (Eq, Show)
instance Arbitrary MyData where
arbitrary = oneof [genI, genB]
where genI = fmap I arbitrary
genB = fmap B arbitrary
The genI and genB generators use the underlying Arbitrary instances of Int and Bool by mapping raw integers and Boolean values to the respective case constructors.
Here's a set of sample data:
> sample (arbitrary :: Gen MyData)
B False
B False
I 2
B False
I 1
I 7
B False
B False
B True
I 7
B False
As you can see, it also accomplishes to pick arbitrary integers.
The code in the OP has several problems. The first error message is that the return type is nested. One way to get around that is to remove the do notation. This, however, doesn't solve the problem.
Even if you reduce it to the following, it doesn't type-check:
instance Arbitrary MyData where
arbitrary =
frequency [(1, return (I 1)),
(1, choose(B True, B False))]
This attempt produces the error:
Q72160684.hs:10:21: error:
* No instance for (random-1.1:System.Random.Random MyData)
arising from a use of `choose'
* In the expression: choose (B True, B False)
In the expression: (1, choose (B True, B False))
In the first argument of `frequency', namely
`[(1, return (I 1)), (1, choose (B True, B False))]'
|
10 | (1, choose(B True, B False))]
| ^^^^^^^^^^^^^^^^^^^^^^^
The choose method requires the input to be Random instances, which MyData isn't.
If you really want to use frequency rather than oneof, the easiest way may be to first get oneof to work, since you can view frequency as a generalisation of oneof.
First, to make the code a little more succinct, I've used <$> instead of fmap and then inlined both generators:
instance Arbitrary MyData where
arbitrary = oneof [I <$> arbitrary, B <$> arbitrary]
Now replace oneof with frequency and change each generator to a weighted tuple:
instance Arbitrary MyData where
arbitrary = frequency [(10, I <$> arbitrary), (1, B <$> arbitrary)]
Sampling from this instance illustrates that the distribution is now skewed:
> sample (arbitrary :: Gen MyData)
I 0
I (-2)
I (-4)
I (-1)
I 0
I 8
B True
I 1
I 3
I (-3)
I (-16)
There are 10 I values and only 1 B value.
You can derive it with generic-random (since 1.5.0.0).
Deriving via GenericArbitraryU: Gives a uniform distribution (like oneof from Mark Seemann's answer):
{-# Language DataKinds #-}
{-# Language DeriveGeneric #-}
{-# Language DerivingVia #-}
import Test.QuickCheck
import GHC.Generics
import Generic.Random.DerivingVia
-- ghci> :set -XTypeApplications
-- ghci> sample #MyData arbitrary
-- I 0
-- I 1
-- B True
-- I 6
-- I (-5)
-- I (-7)
-- B True
-- I (-10)
-- B True
-- B True
-- I (-9)
data MyData = I Int | B Bool
deriving
stock (Show, Generic)
deriving Arbitrary
via GenericArbitraryU MyData
Deriving via GenericArbitrary: gives a weighted distribution specified by a type-level list of numbers. They denote the frequency of each constructor (like frequency):
-- ghci> sample #MyData arbitrary
-- I 0
-- I (-2)
-- I 4
-- I 5
-- I 2
-- I 0
-- B False
-- I (-9)
-- I (-10)
-- I (-3)
-- I (-8)
data MyData = I Int | B Bool
deriving
stock (Show, Generic)
deriving Arbitrary
via GenericArbitrary '[10, 1] MyData

Can you "partially" derive a Typeclass?

In the following toy example we create a new type D for which we want to implement the typeclass Show. Now let's say for all constructors the derived show function would be just fine, except for one special case A for which we want to override that default.
Is it possible to do that, or can you just have all or none of them derived?
data D = A | B | C
deriving (Show)
-- goal:
-- show A = "A is special"
-- show B = "B"
-- show C = "C"
main = print $ show A
Try it online!
This can be done using generics. generic-data provides a default implementation of showsPrec, gshowsPrec, and you can use pattern-matching to handle non-default cases before it:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
import Generic.Data (gshowsPrec)
data D = A | B | C
deriving (Generic)
instance Show D where
showsPrec _ A = ("A is special" ++)
showsPrec n x = gshowsPrec n x

How do you sort a list of tuple by one of the tuple-Haskell

I have a list of cards and want to sort list of cards([Card]) by suit but the way Card is defined makes it confusing to navigate. Can someone help me define a simple function to sort the list.
Tried things like :
sortHand ::[Card]-> [Card]
sortHand hand = sort hand
but I can't figure out how to filter the suit only
Card is defined:
data Suit = Spade | Club | Diamond | Heart
deriving (Eq, Ord, Enum, Bounded)
data Rank = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten
| Jack | Queen | King | Ace
deriving (Eq, Ord, Enum, Bounded)
data Card = Card Suit Rank
deriving (Eq)
This is what the sortBy :: (a -> a -> Ordering) -> [a] -> [a] and comparing :: Ord b => (a -> b) -> (b -> b -> Ordering) functions are for. The first lets you sort by a custom ordering, the other lets you define an ordering by mapping a's to some b which has an ordering (a card to a suit in this example).
You could use these together to define
sortBySuit hand = sortBy (comparing $ \(Card suit _) -> suit) hand
Note however due to how the automatically derived Ord instances work your Card type would already be ordered by suit first and then rank if you just added a deriving Ord to your data definition.
This is easy if you make Card a record type:
data Card = Card { cardSuit::Suit, cardRank::Rank }
deriving (Eq)
*Main> :m +Data.List
*Main Data.List> :m +Data.Ord
*Main Data.List Data.Ord> sortBy (comparing cardSuit) [Card Club Three, Card Diamond Two, Card Spade Eight, Card Spade Five]
[Card {cardSuit = Spade, cardRank = Eight},Card {cardSuit = Spade, cardRank = Five},Card {cardSuit = Club, cardRank = Three},Card {cardSuit = Diamond, cardRank = Two}]

Storing an Enum type in an unboxed Vector

Suppose I have something like this:
data Colour = Red | Blue | Green
deriving (Eq, Ord, Enum, Bounded, Read, Show)
And I want to have an unboxed Vector of Colours. I obviously cannot do this directly (because Colour isn't an instance of Unbox), but I also can't tell how I would write the Unbox instance for Colour. The the documentation for Unbox doesn't seem to say how you make something an instance of it (or at least, not in a way I understand).
One approach is to use Data.Vector.Unboxed.Deriving, which uses template Haskell to define the correct instances for the new types in terms of existing types with Unbox instances.
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, TemplateHaskell #-}
module Enum where
import qualified Data.Vector.Unboxed as U
import Data.Vector.Generic.Base
import Data.Vector.Generic.Mutable
import Data.Vector.Unboxed.Deriving
import Data.Word
data Colour = Red | Blue | Green
deriving (Eq, Ord, Enum, Bounded, Read, Show)
colourToWord8 :: Colour -> Word8
colourToWord8 c =
case c of
Red -> 0
Blue -> 1
Green -> 2
word8ToColour :: Word8 -> Colour
word8ToColour w =
case w of
0 -> Red
1 -> Blue
_ -> Green
derivingUnbox "Colour"
[t| Colour -> Word8 |]
[| colourToWord8 |]
[| word8ToColour |]
test n = U.generate n (word8ToColour . fromIntegral . (`mod` 3))
Of course this wastes space in this case because we only use 2 of the 8 bits in Word8.

Resources