Haskell: Filter set based on member type? - haskell

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

Related

A lens for getting or setting a record field determined by a runtime argument

I have these types (and more):
data Player = PlayerOne | PlayerTwo deriving (Eq, Show, Read, Enum, Bounded)
data Point = Love | Fifteen | Thirty deriving (Eq, Show, Read, Enum, Bounded)
data PointsData =
PointsData { pointsToPlayerOne :: Point, pointsToPlayerTwo :: Point }
deriving (Eq, Show, Read)
I'm doing the Tennis kata, and as part of the implementation, I'd like to use some functions that enable me to get or set the points for an arbitrary player, only known at runtime.
Formally, I need functions like these:
pointFor :: PointsData -> Player -> Point
pointFor pd PlayerOne = pointsToPlayerOne pd
pointFor pd PlayerTwo = pointsToPlayerTwo pd
pointTo :: PointsData -> Player -> Point -> PointsData
pointTo pd PlayerOne p = pd { pointsToPlayerOne = p }
pointTo pd PlayerTwo p = pd { pointsToPlayerTwo = p }
As demonstrated, my problem isn't that I can't implement these functions.
They do, however, look lens-like to me, so I wonder if I could get that functionality via the lens library?
Most of the lens tutorials show how to get or set a particular, named part of a bigger data structure. This doesn't quite seem to fit what I'm trying to do here; rather, I'm trying to get or set a sub-part determined at runtime.
An excursion into somewhat abstract typeclasses. Your PointsData has a special relationship with the Player type. It's a bit like a Map Player Point, with the particularity that for every possible value of Player, there's always a corresponding Point. In a way, PointsData is like a "reified function" Player -> Point.
If we make PointsData polymorphic on the type of Points, it would fit with the Representable typeclass. We would say that PointsData is "represented" by Player.
Representable is often useful as an interface to tabular data, like in the grids package.
So one possible solution would be to turn PointsData into an actual Map, but hide the implementation behind a smart constructor that took a Player -> Point function to initialize it for all possible keys (it would correspond to the tabulate method of Representable).
The user should not be able to delete keys from the map. But we could piggyback on the Ixed instance of Map to provide traversals.
import Control.Lens
import Data.Map.Strict -- from "containers"
newtype PointsData = PointsData { getPoints :: Map Player Point }
init :: (Player -> Point) -> PointsData
init f = PointsData (Data.Map.Strict.fromList ((\p -> (p, f p)) <$> [minBound..maxBound]))
playerPoints :: Player -> Lens' PointsData Point
playerPoints pl = Control.Lens.singular (iso getPoints PointsData . ix pl)
You could create a function that produces a Lens given a Player, like this:
playerPoints :: Player -> Lens' PointsData Point
playerPoints PlayerOne = field #"pointsToPlayerOne"
playerPoints PlayerTwo = field #"pointsToPlayerTwo"
(this is using field from generic-lens)
Usage would be like this:
pts :: PointsData
pl1 = pts ^. playerPoints PlayerOne
pl2 = pts ^. playerPoints PlayerTwo
newPts = pts & playerPoints PlayerOne .~ 42
P.S. Or were you looking for picking a field of PointsData by matching field name to Player constructor name? That is also possible via Generic, but doesn't seem worth the trouble.
Based on the answer from Fyodor Soikin and comment from duplode, I ended up using makeLenses from lens and writing a function that returns the appropriate lens:
data PointsData =
PointsData { _pointsToPlayerOne :: Point, _pointsToPlayerTwo :: Point }
deriving (Eq, Show, Read)
makeLenses ''PointsData
playerPoint :: Player -> Lens' PointsData Point
playerPoint PlayerOne = pointsToPlayerOne
playerPoint PlayerTwo = pointsToPlayerTwo
It can be used like this fragment of a bigger function:
score :: Score -> Player -> Score
-- ..
score (Points pd) winner = Points $ pd & playerPoint winner %~ succ
-- ..

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.

Allowing multiple declarations of data constructors

I am currently experimenting with data types and I've ran into an issue involving multiple declarations of data constructors.
data DBPosition = Unknown
| Omega Integer
| Delta Integer
deriving (Show, Eq, Ord)
data DBGeometry = Unknown | Cis | Trans
deriving (Show, Eq, Ord)
data DoubleBond = DoubleBond DBPosition DBGeometry
deriving (Show, Eq, Ord)
If I was to make a value such as - let bond = DoubleBond Unknown Unknown, then it could be inferred that the first Unknown has a type of DBPosition while the second Unknown has a type of DBPosition. Unfortunately this is not the case:
test.hs:6:27:
Multiple declarations of `Unknown'
Declared at: test.hs:1:27
test.hs:6:27
Failed, modules loaded: none.
Are there any language extensions that can be used to get around this?
As Carsten pointed out above, your definition does not work because you have two constructors with the same name. You'd need to use e.g. UnknownDBPosition and UnknownDBGeometry. However, I'd argue a better solution arises from recognising:
That the concept of an unknown value works in precisely the same way no matter if you are talking about double bond positions, geometries, or whatever else; and
That Unknown is not actually a variety of double bond geometry or position.
That being so, I recommend that you remove both Unknown and use Maybe to specify lack of knowledge.
data DBPosition = Omega Integer
| Delta Integer
deriving (Show, Eq, Ord)
data DBGeometry = Cis | Trans
deriving (Show, Eq, Ord)
data DoubleBond = DoubleBond (Maybe DBPosition) (Maybe DBGeometry)
deriving (Show, Eq, Ord)

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]

Haskell's algebraic data types: "pseudo-extend"

I am learning about Algebraic DTs in haskell. What I would like to do is create a new ADT that kind of "extends" an existing one. I cannot find how to express what I would like, can someone sugest an alternative pattern or sugest a solution. I want them to be distinct types, but copying and pasting just seams like a silly solution. The code below best describes what I am seeking.
data Power =
Abkhazia |
-- A whole bunch of World powers and semi-powers
Transnistria
deriving (Eq, Show)
data Country =
--Everything in Power |
Netural |
Water
deriving (Eq, Show)
Edit: I think It need a little clarification... I want to be able to do this (in ghci)
let a = Abkhazia :: Country
and not
let a = Power Abkhazia :: Country
You need to represent them as a tree:
data Power
= Abkhazia
| Transnistria
deriving (Eq, Show)
data Country
= Powers Power -- holds values of type `Power`
| Netural -- extended with other values.
| Water
deriving (Eq, Show)
Edit: your extension to the question makes this a bit simpler: both the Country and Power types share some common behavior as "countries". This suggests you use the open, extensible type class feature of Haskell to given common behaviors to the data type. E.g.
data Power = Abkhazia | Transistria
data Countries = Neutral | Water
then, a type class for things both Power and Countries share:
class Countrylike a where
landarea :: a -> Int -- and other things country-like entities share
instance Countrylike Power where
landarea Abkhazia = 10
landarea Transistria = 20
instance Countrylike Countries where
landarea Neutral = 50
landarea Water = 0
then you can use landarea cleanly on either powers or countries. And you can extend it to new types in the future by adding more instances.
{-# LANGUAGE GADTs, StandaloneDeriving #-}
data POWER
data COUNTRY
data CountryLike a where
Abkhazia :: CountryLike a
Transnistria :: CountryLike a
Netural :: CountryLike COUNTRY
Water :: CountryLike COUNTRY
deriving instance Show (CountryLike a)
deriving instance Eq (CountryLike a)
type Power = CountryLike POWER
type Country = CountryLike COUNTRY
foo :: Power
foo = Abkhazia
bar :: Country
bar = Abkhazia
baz :: Country
baz = Netural
Edit: An alternative would be type Power = forall a. CountryLike a (Advantage: Makes Power a subtype of Country. Disadvantage: This would make e.g. Power -> Int a higher-rank type, which tend to be annoying (type inference etc.))

Resources