Allowing multiple declarations of data constructors - haskell

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)

Related

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

Hide fields from deriving (Show)

Imagine I have a data record with many fields:
data DataRecord = DataRecord {
field1 :: String,
field2 :: String,
...
} deriving (Show)
Is it possible to hide some fields from the deriving (Show) or do have to implement my own show function for DataRecord?
Reason for my question: When I have cyclic dependencies between two data records both using deriving (Show) the show function would generate an infinite string.
The Haskell 2010 report mentions your cyclic dependencies as unsuitable case:
The derived Read and Show instances may be unsuitable for some uses. Some problems include:
Circular structures cannot be printed or read by these instances.
So you need to specify the instance by hand.

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.

How to create a type bounded within a certain range

I would like to create a new integral type which is bounded to a certain range. I have tried:
data PitchClass = PC Int deriving (Ord, Eq, Show)
instance Bounded PitchClass where
minBound = PC 0
maxBound = PC 11
However, what I want is something that will fail if something like
PC 12
or
PC (-1)
is attempted.
Is the general approach for a situation in which you wish to place constraints on creating new types one in which the value constructors are not exported from the module, but rather functions which return instances of the type and which perform constraint checks are exported?
Yes, not exporting the data constructor from the module is the way to go.
Instead, you export a function which does the checking as you said. This is often called a smart constructor.
An alternate solution for cases where the number of total values is this small is to simply enumerate the possible constructors.
data PitchClass = A | Bb | B | C | Db | D | Eb | E | F | Gb | G | Ab
deriving (Eq, Ord, Bounded, Show, Read)
There are half a dozen different hacks you can try from here to make it more convenient in various ways; for example, you can derive Enum to get toEnum . fromEnum = id (and toEnum (-1) = {- an exception -}), or you can write a custom Integral instance to get 0 = A (and your choice of behavior for -1).

Resources