Storing an Enum type in an unboxed Vector - haskell

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.

Related

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

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))

Get data of type without pattern match on all data contructors

Is there a way to make abstraction of the data type and just use the values?
data Color a = Blue a | Green a | Red a | Yellow a | Magenta a deriving (Show)
Something like :
calcColor :: Color a -> Color a -> Maybe a
calcColor (_ x) (_ y) = Just $ x + y
It doesn't have to be necessarily in the function declaration.
One option I was thinking was to have something like fromJust but even that feels a little redundant.
fromColor :: Color a -> a
fromColor (Blue t) = t
fromColor (Red t) = t
fromColor (Green t) = t
fromColor (Yellow t) = t
Edit - added context and more clarifications
From the way I managed to question it, the title might look like a duplicate question.
I'm not that sure, but that is for the community to decide.
I pretty new to Haskell so maybe my question looks stupid but still I think it's a valid case because I actually have this situation.
#FyodorSoikin, #leftaroundabout Your answers helps me, but partially. I'll try make explain better what exactly I would like to achive.
I want to think at the Color type like a category (let's say G), the colors beeing elements of the G,
and I also have phones that come in different colors. The phones category (let's say H).
Now I have I try to come with a way to make use of the morphisms (functions) of the G category using a functor in the H category or the other way around.
For example : determine the future stocks of a color type based on the sales of phones.
I want to understand to what extend I can create a types like Color to have the advantages of a type ustead of using a string value.
You could do a hack like
{-# LANGUAGE DeriveFoldable #-}
import Data.Foldable (Foldable, toList)
data Color a = Blue a | Green a | Red a | Yellow a | Magenta a
deriving (Show, Foldable)
fromColor :: Color a -> a
fromColor c = case toList c of
[ca] -> ca
_ -> error "Impossible, `Color` has only one field."
But I agree with Fyodor Soikin's comment: why have the a field in each constructor in the first place? Just factor it out
data Hue = Blue | Green | Red | Yellow | Magenta
data Color a = Color { hue :: Hue, value :: a }
Based on your edit, it looks like you are looking for a basic vocabulary for dealing with Color. That can be provided both by class instances and by special-purpose functions.
A Functor instance, for example, allows you to change the a value in a Color a independently of the color itself:
data Hue = Blue | Green | Red | Yellow | Magenta
deriving (Eq, Show)
data Color a = Color { hue :: Hue, value :: a }
deriving (Eq, Show)
instance Functor Color where
fmap f (Color h a) = Color h (f a)
GHCi> test1 = Color Red 27
GHCi> fmap (2*) test1
Color {hue = Red, value = 54}
Two brief notes:
The things I'm suggesting here can be done equally as well with your four-constructor Color type or with leftaroundabout's single-constructor one. The latter, though, should be easier to work with in most situations, so I'll stick with it.
The DeriveFunctor extension means you almost never have to write a Functor instance explicitly: turn it on by adding {-# LANGUAGE DeriveFunctor #-} to the top of your file and then just write:
data Color a = Color { hue :: Hue, value :: a }
deriving (Eq, Show, Functor)
Another thing you might want to do is having a Hue -> Colour a -> Maybe a function, which would give you a way to use operations on Maybe to filter the a values by their attached hue:
colorToMaybe :: Hue -> Color a -> Maybe a
colorToMaybe chosenHue col
| hue col == chosenHue = Just (value col)
| otherwise = Nothing
GHCi> test1 = Color Red 27
GHCi> test2 = Color Red 14
GHCi> test3 = Color Blue 33
GHCi> import Data.Maybe
GHCi> mapMaybe (colorToMaybe Red) [test1, test2, test3]
[27,14]
GHCi> import Control.Applicative
GHCi> liftA2 (+) (colorToMaybe Red test1) (colorToMaybe Red test2)
Just 41
GHCi> liftA2 (+) (colorToMaybe Red test1) (colorToMaybe Red test3)
Nothing
These are just rather arbitrary suggestions. The specifics of what you'll want to define will depend on your use cases.

Haskell: Filter set based on member type?

Let's say I have the following data structure in Haskell to represent a Checkers
/Draughts piece:
data Piece = Reg {pos :: Square, color :: Color}
| King {pos :: Square, color :: Color}
deriving (Show, Eq)
Given a list of these Pieces, how might I isolate the Kings from the list? I've been looking at the documentation for Data.Set at http://www.haskell.org/ghc/docs/7.6.2/html/libraries/containers-0.5.0.0/Data-Set.html but couldn't find something that seemed obvious to me.
In short, I need a method that will, given a Data.Set set of Piece, return the subset of all King type pieces. I feel like it's something very simple but that I haven't encountered yet because I'm new to the Data.Set class in Haskell.
You can define a Boolean function isKing and then use filter in Data.Set, as follows:
import Data.Set as S
data Color = Int deriving (Show, Eq)
data Square = Square (Int,Int) deriving (Show, Eq)
data Piece = Reg {pos :: Square, color :: Color}
| King {pos :: Square, color :: Color}
deriving (Show, Eq)
isKing King{} = True
isKing _ = False
getKings s = S.filter isKing s

How do I create an unbox instance of an ADT?

I'm having trouble finding good resources that work for how to make my data types unboxed, for use in an unboxed vector. How would I make the data type
data Color = Yellow | Red | Green | Blue | Empty deriving (Show, Eq)
be an instance of Unbox?
Edit: after poking around a bit more, it seems that by forcing paramaters in some functions to be strict, I can convince GHC to unbox them automatically. If this applicable in my case? How do I know which paramaters to make strict?
You can use the vector-th-unbox package to derive the instance for you. You just need to provide conversion functions to and from some existing Unbox type:
colorToWord8 :: Color -> Word8
colorToWord8 = ...
word8ToColor :: Word8 -> Color
word8ToColor = ...
derivingUnbox "Color"
[t| Color -> Word8 |]
colorToWord8
word8ToColor
GeneralizedNewtypeDeriving won't help you here because you're dealing with a 'full-blown' ADT, rather than a newtype wrapping something that's already an instance of Unbox.
Your data type is more suited to boxed vectors. Use Data.Vector.Unboxed if you need to hold more primitive numeric types like Doubles, Ints, etc. Perhaps you can make Color an instance of Unbox, but it almost certainly isn't worth the hassle. Import Data.Vector and you'll be set:
import qualified Data.Vector as V
Color = Red | Blue deriving Show
someColors :: V.Vector Color
someColors = V.fromList [Red, Blue, Blue, Red]

General conversion type class

I'd like to see if it is feasible to have a type class for converting one thing into another and back again from a mapping of [(a,b)].
This example should illustrate what I'd like to do:
data XX = One | Two | Three deriving (Show, Eq)
data YY = Eno | Owt | Eerht deriving (Show, Eq)
instance Convert XX YY where
mapping = [(One, Eno), (Two, Owt), (Three, Eerht)]
-- // How can I make this work?:
main = do print $ (convert One :: YY) -- Want to output: Eno
print $ (convert Owt :: XX) -- Want to output: Two
Here's my stab at making this work:
{-# LANGUAGE MultiParamTypeClasses #-}
import Data.Maybe(fromJust)
lk = flip lookup
flipPair = uncurry $ flip (,)
class (Eq a, Eq b) => Convert a b where
mapping :: [(a, b)]
mapping = error "No mapping defined"
convert :: a -> b
convert = fromJust . lk mapping
-- // This won't work:
instance (Convert a b) => Convert b a where
convert = fromJust . lk (map flipPair mapping)
It is easy to do this with defining two instances for the conversion going either way but I'd like to only have to declare one as in the first example. Any idea how I might do this?
Edit: By feasible I mean, can this be done without overlapping instances any other nasty extensions?
I, er... I almost hate to suggest this, because doing this is kinda horrible, but... doesn't your code work as is?
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverlappingInstances #-}
import Data.Maybe(fromJust)
lk x = flip lookup x
flipPair = uncurry $ flip (,)
class (Eq a, Eq b) => Convert a b where
mapping :: [(a, b)]
mapping = error "No mapping defined"
convert :: a -> b
convert = fromJust . lk mapping
instance (Convert a b) => Convert b a where
convert = fromJust . lk (map flipPair mapping)
data XX = One | Two | Three deriving (Show, Eq)
data YY = Eno | Owt | Eerht deriving (Show, Eq)
instance Convert XX YY where
mapping = [(One, Eno), (Two, Owt), (Three, Eerht)]
main = do print $ (convert One :: YY)
print $ (convert Owt :: XX)
And:
[1 of 1] Compiling Main ( GeneralConversion.hs, interpreted )
Ok, modules loaded: Main.
*Main> main
Eno
Two
*Main>
I'm not sure how useful such a type class is, and all the standard disclaimers about dubious extensions apply, but that much seems to work. Now, if you want to do anything fancier... like Convert a a or (Convert a b, Convert b c) => Convert a c... things might get awkward.
I suppose I might as well leave a few thoughts about why I doubt the utility of this:
In order to use the conversion, both types must be unambiguously known; likewise, the existence of a conversion depends on both types. This limits how useful the class can be for writing very generic code, compared to things such as fromIntegral.
The use of error to handle missing conversions, combined with the above, means that any allegedly generic function using convert will be a seething pit of runtime errors just waiting to happen.
To top it all off, the generic instance being used for the reversed mapping is in fact a universal instance, only being hidden by overlapped, more specific instances. That (Convert a b) in the context? That lets the reversed mapping work, but doesn't restrict it to only reversing instances that are specifically defined.

Resources