How do I create an unbox instance of an ADT? - haskell

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]

Related

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.

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.

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

Haskell interdependent datatype tree aesthetics

I have made an interdependent tree of datatypes as below. PT being the 'root'-datatype. There are functions that should combine the lower datatypes to the root. This way, Giving these functions the type signature (a -> b -> ... -> PT), requires me to include a lot of information to get to lower datatypes (PTCmd CmdSub Hp ...). This descent down the datatype tree is irrelevant and i wouldn't like to include this information in the result.
If I define all the lower datatypes in PT itself, the datatype definition harder to read.
Besides adding worthless information to the result, and a single huge datatype definition, is there another, preferably less of an eyesore, way to have my functions result in the root datatype PT?
data PT = PTCmd Command | PTVal V | PTCon C
deriving (Eq, Show)
data Command = CmdSub Sub | ...
deriving (Eq, Show)
data SubCommand = Hp V C | ...
deriving (Eq, Show)
Perhaps you could define some "smart constructors"; for example:
cmdSub = PTCmd . CmdSub
hp = cmdSub . Hp
If you can afford using GHC 7.8 then you should look at the PatternSynonyms extension, as it addresses your issues quite well.

Template Haskell data declarations that derive Show

The following doesn't compile:
import Language.Haskell.TH
makeAlpha n = [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]
I can't make out what the error means at all:
Can't derive instances where the instance context mentions
type variables that are not data type parameters
Offending constraint: Show t_d
When deriving the instance for (Show Alpha)
In the Template Haskell quotation
[d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]
In the expression:
[d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]
Is it possible to do derivations like this?
This problem arises because TH quotes are type checked when they are compiled, with splices replaced by variables. This is usually a good idea, because it allows many kinds of problems to be detected before the splice is run, but in some cases this can make the compiler wrongfully reject a splice that would generate valid code.
In this case, this means that the compiler tries to check this code:
data Alpha = Alpha t deriving (Show, Read)
This doesn't work because the derived Show and Read instances need to use Show and Read for t, but since t is not a type parameter of Alpha, it cannot add the necessary constraints. Of course, when this splice is run, t is replaced by a concrete type, so the appropriate instances will be available without the need for any constraints, so this is one of the cases where the compiler is being over-cautious.
The workaround is to not use quoting, but instead use TH combinators, which are not subject to these extra checks. It's messy, but it works:
makeAlpha n = sequence [dataD (cxt []) alpha []
[normalC alpha [strictType notStrict (conT n)]] [''Show, ''Read]]
where alpha = mkName "Alpha"
There has been some talk about relaxing the checks done on quotes, but for now you'll just have to deal with it.

Resources