Algebraic data type (intended) name collision.. how to? - haskell

I had the idea to implement my own little music theory module in Haskell.
Starting with notes (Note) makes sense and right there and then I ran into this nasty syntactic problem, I have no idea how real Haskellers handle it.
data Note = Sharp NoteS | Flat NoteF deriving (Show)
data NoteS =
C | SC | D | SD | E | F | SF | G | SG | B
deriving (Ord,Show,Eq)
data NoteF =
C | FD | D | FE | E | F | FG | G | FB | B
deriving (Ord,Show,Eq)
instance Eq Note where
(==) (NoteS n1) (NoteS n2) = n1 == n2
(==) (NoteF n1) (NoteF n2) = n1 == n2
(==) (NoteS n1) (NoteF n2) = ???
(==) (NoteF n1) (NoteS n2) = ???
...
flatToSharp :: Note -> NoteS
sharpToFlat :: Note -> NoteF
As most might know, a sharp C and a flat D are synonymous in general but sometimes it is prefered to use one or the other depending on context. So I hoped to use the fact that both NoteS and NoteF are instances of Ord (e.g. for interval calculation). But in both representations, the plain notes (C,D,E,F...) have the same names in both types.
Now I could think of ways to "hack" around this syntactic problem. But it would either have ugly syntactic implications or run time implications (e.g. use Strings instead of a types, lots of testing and error checking,...).
So here is my question to Haskell professionals... How would I do it in the spirit of my idea without too many concessions to this "namespace" problem of Haskell?
I tried {-# LANGUAGE DuplicateRecordFields #-} but it does not help with unions, obviously.

If you must keep the data representation as you have it there, the standard namespacing mechanism in Haskell is modules. So you could write
module Sharps where data NoteS = ...
module Flats where data NoteF = ...
module Main where
import Sharps as S
import Flats as F
(Of course, don't forget that for GHC, each module must go in its own file with an appropriate filename.) Then, in Main, you could refer to Sharps.C or S.C to get the NoteS constructor, and Flats.C or F.C to get the NoteF constructor.
But may I propose a different solution? How about naming the natural notes, and simply having a type that records how sharp or flat you've gone from there? After all, you're going to want to handle double sharps and double flats eventually, I'm sure. So:
data Natural = A | B | C | D | E | F | G
data Note = Note
{ natural :: Natural
, offset :: Int -- positive for sharp, negative for flat, say
}
(There are many other data representation choices you could make as well.)

Another idea is to use a pattern synonym. You can have a single type representing notes, and synonyms to rename some of them.
https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#pattern-synonyms
{-# LANGUAGE PatternSynonym #-}
data Note = C | SC | D | SD | E | F | SF | G | SG | B
pattern FD = SC
pattern FE = SD
pattern FG = SF
pattern FB = SG

Related

Accessing the "default show" in Haskell?

Say you have a data-structure (borrowed from this question):
data Greek = Alpha | Beta | Gamma | Delta | Eta | Number Int
Now one can make it an instance of Show by appending deriving Show on that instruction.
Say however we wish to show Number Int as:
instance Show Greek where
show (Number x) = show x
-- ...
The problem is that one must specify all other parts of the Greek data as well like:
show Alpha = "Alpha"
show Beta = "Beta"
For this small example that's of course doable. But if the number of options is long, it requires a large amount of work.
I'm wondering whether it is possible to access the "default show" implementation and call it with a wildcard. For instance:
instance Show Greek where
show (Number x) = show x
show x = defaultShow x
You thus "implement" the specific patterns that differ from the default approach and the remaining patterns are resolved by the "fallback mechanism".
Something a bit similar to method overriding with a reference to super.method in object oriented programming.
As #phg pointed above in the comment this can be also done with the help of generic-deriving:
{-# LANGUAGE DeriveGeneric #-}
module Main where
import Generics.Deriving.Base (Generic)
import Generics.Deriving.Show (GShow, gshow)
data Greek = Alpha | Beta | Gamma | Delta | Eta | Number Int
deriving (Generic)
instance GShow Greek
instance Show Greek where
show (Number n) = "n:" ++ show n
show l = gshow l
main :: IO ()
main = do
print (Number 8)
print Alpha
You can sorta accomplish this using Data and Typeable. It is a hack of course, and this example only works for "enumerated" types as in your example.
I'm sure we could get more elaborate with how we do this, but to cover your given example:
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Data
import Data.Typeable
data Greek = Alpha | Beta | Gamma | Delta | Eta | Number Int
deriving (Data,Typeable)
instance Show Greek where
show Number n = show n
show x = show $ toConstr x
This approach as I've implemented it cannot handle nested data structures or anything else remotely fancy, but again, this is an ugly hack. If you really must use this approach you can dig around in the Data.Data package I'm sure you could piece something together...
Here is a blog post giving a quick introduction to the packages: http://chrisdone.com/posts/data-typeable
The proper way to go about this would be to use a newtype wrapper. I realize that this isn't the most convenient solution though, especially when using GHCi, but it incurs no additional overhead, and is less likely to break in unexpected ways as your program grows.
data Greek = Alpha | Beta | Gamma | Delta | Eta | Number Int
deriving (Show)
newtype SpecialPrint = SpecialPrint Greek
instance Show SpecialPrint where
show (SpecialPrint (Number x)) = "Number: " ++ show x
show (SpecialPrint x) = show x
main = do
print (SpecialPrint Alpha)
print (SpecialPrint $ Number 1)
No, that's not possible AFAIK.
Further, custom instances of Show deserve a second thought, because Show and Read instances should be mutually compatible.
For just converting to human (or whoever) readable strings, use your own function or own typeclass. This will also achieve what you want:
Assuming you have a Presentable typeclass with a method present, and also the default Show instance, you can write:
instance Presentable Greek where
present (Number x) = show x
present x = show x

haskell type,new type or data for only an upper case char

If i want to make a String but holds only an uppercase character. I know that String is a [Char]. I have tried something like type a = ['A'..'Z'] but it did not work any help?
What you're wanting is dependent types, which Haskell doesn't have. Dependent types are those that depend on values, so using dependent types you could encode at the type level a vector with length 5 as
only5 :: Vector 5 a -> Vector 10 a
only5 vec = concatenate vec vec
Again, Haskell does not have dependent types, but languages like Agda, Coq and Idris do support them. Instead, you could just use a "smart constructor"
module MyModule
( Upper -- export type only, not constructor
, mkUpper -- export the smart constructor
) where
import Data.Char (isUpper)
newtype Upper = Upper String deriving (Eq, Show, Read, Ord)
mkUpper :: String -> Maybe Upper
mkUpper s = if all isUpper s then Just (Upper s) else Nothing
Here the constructor Upper is not exported, just the type, and then users of this module have to use the mkUpper function that safely rejects non-uppercase strings.
For clarification, and to show how awesome dependent types can be, consider the mysterious concatenate function from above. If I were to define this with dependent types, it would actually look something like
concatenate :: Vector n a -> Vector m a -> Vector (n + m) a
concatenate v1 v2 = undefined
Wait, what's arithmetic doing in a type signature? It's actually performing type-system level computations on the values that this type is dependent on. This removes a lot of potential boilerplate in Haskell, and it makes guarantees at compilation time that, e.g., arrays can't have negative length.
Most desires for dependent types can be filled either using smart constructors (see bheklilr's answer), generating Haskell from an external tool (Coq, Isabelle, Inch, etc), or using an exact representation. You probably want the first solution.
To exactly represent just the capitals then you could write a data type that includes a constructor for each letter and conversion to/from strings:
data Capital = CA | CB | CC | CD | CE | CF | CG | CH | CI | CJ | CK | CL | CM | CN | CO | CP | CQ | CR | CS | CT | CU | CV | CW | CX | CY | CZ deriving (Eq, Ord, Enum)
toString :: [Capital] -> String
toString = map (toEnum . (+ (fromEnum 'A')) . fromEnum)
You can even go a step further and allow conversion from string literals, "Anything in quotes", to a type [Capitals] by using the OverloadedStrings extension. Just add to the top of your file {-# LANGUAGE OverloadedStrings, FlexibleInstances #-}, be sure to import Data.String and write the instance:
type Capitals = [Capital]
instance IsString Capitals where
fromString = map (toEnum . (subtract (fromEnum 'A')) . fromEnum) . filter (\x -> 'A' <= x && x <= 'Z')
After that, you can type capitals all you want!
*Main> toString ("jfoeaFJOEW" :: Capitals)
"FJOEW"
*Main>
bheklilr is correct but perhaps for your purposes the following could be OK:
import Data.Char(toUpper)
newtype UpperChar = UpperChar Char
deriving (Show)
upperchar :: Char -> UpperChar
upperchar = UpperChar. toUpper
You can alternatively make UpperChar an alias of Char (use type instead of newtype) which would allow you to forms lists of both Char and UpperChar. The problem with an alias, however, is that you could feed a Char into a function expecting an UpperChar...
One way to do something similar which will work well for the Latin script of your choice but not so well as a fully general solution is to use a custom type to represent upper case letters. Something like this should do the trick:
data UpperChar = A|B|C|D| (fill in the rest) | Y | Z deriving (Enum, Eq, Ord, Show)
newtype UpperString = UpperString [UpperChar]
instance Show UpperString
show (UpperString s) = map show s
The members of this type are not Haskell Strings, but you can convert between them as needed.

What's the most efficient way to represent finite (non-recursive) algebraic type values?

What's the most efficient way to serialize finite (non-recursive) algebraic-data-types which are comprised only of constructors?
e.g.
p = A
| B q
q = C
| D r
| E
r = F
| G
Manually enumerating all valid combinations for this trivially small definition is possible:
A 0x00
B C 0x01
B D F 0x02
B D G 0x03
B E 0x04
Is there any broader theory here?
How about if we then add non-constructor types, such as ints, etc.?
How does Haskell represent these in memory (it allows recursion, so pointers/references will probably be necessary)?
There's no completely standard class that does this, but it's pretty easy to make one yourself. I'll sketch one way of doing this:
data P = A | B Q deriving Show
data Q = C | D R | E deriving Show
data R = F | G deriving Show
class Finite a where
allValues :: [a]
instance Finite P where
allValues = [A] ++ map B allValues
instance Finite Q where
allValues = [C] ++ map D allValues ++ [E]
instance Finite R where
allValues = [F] ++ [G]
I've written the instances this way to show that it's very easy and mechanical and could be done by a program (e.g. with generic programming or with Template Haskell). You could also add an instance to do some legwork for you, provided the type is Bounded and Enumerable:
instance (Bounded a, Enum a) => Finite a where
allValues = [minBound..maxBound]
If you now add deriving (Bounded, Show) to R, that's one less instance to write!
Anyway, now we can evaluate allValues :: [P] and get back [A,B C,B (D F),B (D G),B E] - which you can then zip with [0..] to get your encoding and so on.
But surely this has been done before! I'm not using serialization much (if ever), but a quick search shows that the binary package and the binary-derive package can do something similar for you, without having to write the instances yourself. I would see if those do what you want first.
As for in-memory haskell representations, we can't represent things fully packed typically since the structures are lazy, and that means we need an indirection at each level. That said, unpacking will let you crush these things together. But, as far as I know, it won't pack bits from nested constructors into the same word.
There is a pointer-tagging optimization that shoves some information about the constructor in the pointer that directs to it: http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/HaskellExecution/PointerTagging
For more on unpacking see this: http://www.haskell.org/haskellwiki/Performance/Data_types#Unpacking_strict_fields

Haskell way to go about enums

I want to represent a type of the following form :
(Card, Suit)
to represent cards in a card game where Card instances would be in the set:
{2, 3, 4, 5, 6, 7, 8, 9, J, Q, K, 1}
and Suit would have instances in the set:
{S, D, H, C}
I'd handle that with two Data declarations if that wasn't for the numbers:
data Suit = S | D | H | C deri...
but obviously adding numbers to those null arity types will fail.
So my question is, how to simulate the kind of enum you find in C?
I guess I'm misundestanding a basic point of the type system and help will be appreciated!
EDIT: I'll add some context: I want to represent the data contained in this Euler problem, as you can check, the data is represented in the form of 1S for an ace of spade, 2D for a 2 of diamond, etc...
What I'd really like is to be able to perform a read operation directly on the string to obtain the corresponding object.
I actually happen to have an implementation handy from when I was developing a poker bot. It's not particularly sophisticated, but it does work.
First, the relevant types. Ranks and suits are enumerations, while cards are the obvious compound type (with a custom Show instance)
import Text.ParserCombinators.Parsec
data Suit = Clubs | Diamonds | Hearts | Spades deriving (Eq,Ord,Enum,Show)
data Rank = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten
| Jack | Queen | King | Ace deriving (Eq,Ord,Enum,Show)
data Card = Card { rank :: Rank
, suit :: Suit } deriving (Eq,Ord,Bounded)
instance Show Card where
show (Card rank suit) = show rank ++ " of " ++ show suit
Then we have the parsing code, which uses Parsec. You could develop this to be much more sophisticated, to return better error messages, etc.
Note that, as Matvey said in the comments, the problem of parsing strings into their representations in the program is (or rather should be) orthogonal to how the enums are represented. Here I've cheated and broken the orthogonality: if you wanted to re-order the ranks (e.g. to have Ace rank below Two) then you would break the parsing code, because the parser depends on the internal representation of Two being 0, Three being 1 etc..
A better approach would be to spell out all of the ranks in parseRank explicitly (which is what I do in the original code). I wrote it like this to (a) save some space, (b) illustrate how it's possible in principle to parse a number into a rank, and (c) give you an example of bad practice explicitly spelled out, so you can avoid it in the future.
parseSuit :: Parser Suit
parseSuit = do s <- oneOf "SDCH"
return $ case s of
'S' -> Spades
'D' -> Diamonds
'H' -> Hearts
'C' -> Clubs
parseRank :: Parser Rank
parseRank = do r <- oneOf "23456789TJQKA"
return $ case r of
'T' -> Ten
'J' -> Jack
'Q' -> Queen
'K' -> King
'A' -> Ace
n -> toEnum (read [n] - 2)
parseCard :: Parser Card
parseCard = do r <- parseRank
s <- parseSuit
return $ Card { rank = r, suit = s }
readCard :: String -> Either ParseError Card
readCard str = parse parseCard "" str
And here it is in action:
*Cards> readCard "2C"
Right Two of Clubs
*Cards> readCard "JH"
Right Jack of Hearts
*Cards> readCard "AS"
Right Ace of Spades
Edit:
#yatima2975 mentioned in the comments that you might be able to have some fun playing with OverloadedStrings. I haven't been able to get it to do much that's useful, but it seems promising. First you need to enable the language option by putting {-# LANGUAGE OverloadedStrings #-} at the top of your file, and include the line import GHC.Exts ( IsString(..) ) to import the relevant typeclass. Then you can make a Card into a string literal:
instance IsString Card where
fromString str = case readCard str of Right c -> c
This allows you to pattern-match on the string representation of your card, rather than having to write out the types explicitly:
isAce :: Card -> Bool
isAce "AH" = True
isAce "AC" = True
isAce "AD" = True
isAce "AS" = True
isAce _ = False
You can also use the string literals as input to functions:
printAces = do
let cards = ["2H", "JH", "AH"]
mapM_ (\x -> putStrLn $ show x ++ ": " ++ show (isAce x)) cards
And here it is in action:
*Cards> printAces
Two of Hearts: False
Jack of Hearts: False
Ace of Hearts: True
data Card = Two | Three | Four | Five | Six
| Seven | Eight | Nine | Ten
| Jack | Queen | King | Ace
deriving Enum
Implementing the Enum typeclass means you can use fromEnum and toEnum to convert between Card and Int.
However, if it's important to you that fromEnum Two is 2, you will have to implement the Enum instance for Card by hand. (The autoderived instance starts at 0, just like C, but there's no way of overriding that without doing it all yourself.)
n.b. You might not need Enum --- if all you want is to use operators like < and == with your Cards, then you need to use deriving Ord.
Edit:
You cannot use read to turn a String of the form "2S" or "QH" into a (Card, Suit) because read will expect the string to look like "(a,b)" (e.g. "(2,S)" in the form you initially asked for, or "(Two,S)" in the form I suggested above).
You will have to write a function to parse the string yourself. You could use a parser (e.g. Parsec or Attoparsec), but in this case it should be simple enough to write by hand.
e.g.
{-# LANGUAGE TupleSections #-}
parseSuit :: String -> Maybe Suit
parseSuit "S" = Just S
...
parseSuit _ = Nothing
parseCard :: String -> Maybe (Card, Suit)
parseCard ('2' : s) = fmap (Two,) (parseSuit s)
...
parseCard _ = Nothing
I’d just prefix the numbers with a letter, or better yet, a word. I’d also not use too many one-letter abbreviations – H, K etc. are downright unreadable.
data Suit = Club | Spade | Heart | Diamond
data Card = Card1 | Card2 | … | Jack | Queen | King | Ace
… But I even prefer dave’s suggestion of using the number words (One, Two) for values instead.

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