Reputation: 3899
I am pretty sure my problem stems from the fact that I am new to Haskell and do not understand the type system completely.
I will use the example used in Haskell's wiki on the type topic
The following Type is defined
data Suit = Club | Diamond | Heart | Spade
Now the first issue is, I would like to implement Show
for every "sub-type" (Club, Diamond, Heart, Spade) but this doesn't seem to work because it is a DataKinds
. So I split it up into their own types. (The properties don't make much sense but I added them to be closer to the real code)
data ClubType = ClubType {
clubName :: String,
icon :: String
}
instance Show ClubType where
show (ClubType cn i) = "name: " ++ cn ++ ", icon: " ++ i
Using them in the Suit type
data Suit = Club ClubType
| Diamond DiamondType
| Heart HeartType
| Spade SpadeType
Now I want to use Suit and the "Sub-Types" (Club, Diamond, Heart, Spade) in a different module
. I exported just Suit (..)
.
Usage
import Module1 (Suit(..))
getSuit :: String -> Suit
getSuit "Club" = getClub
getSuit "Heart" = getHeart
...
getClub :: () -> Club
Now again Club
, Heart
, Diamond
and Spade
cannot be used because they are DataKinds
. How do I use the "sub-types"? Do I need to export all types? If I do, does it conform with the return type of getSuit
?
(Sorry if the example doesn't make a whole lot of sense, but I hope you can follow my desired result)
thanks
Upvotes: 1
Views: 65
Reputation: 60503
Yes it sounds like you don't really understand the type system. I will try my best to clarify where I think you are going wrong. In your example
data Suit = Club | Diamond | Heart | Spade
There is only one type, and that is Suit
. Club
, Diamond
, etc. are not types at all, and you will confuse yourself if you refer to them as "sub-types". The proper name for them is constructors, and they are essentially values of type Suit
Club :: Suit
Diamond :: Suit
...
So you can't really implement a Show
instance for "each one", you can only implement a Show
instance for the whole type Suit
, in the usual way, by pattern matching on the constructors:
instance Show Suit where
show Club = "Clubs"
show Diamond = "Diamonds"
show Heart = "Heart"
show Spade = "Spade"
This defines a single function show
on the type Suit -> String
, again there is no "sub-type" anything going on. I wonder if this was all you were looking for.
Since you mention datakinds, using the constructors at the type level still does not make them types -- they are still values of type Suit
. An example of using them at the type level is to index a GADT by these:
data Card :: Suit -> * where
QueenOfSpades :: Card Spade
OtherCard :: Int -> Card s -- we'd want to encode the suit s at the data
-- level too using a singleton, out of scope
-- for this post
But this is fairly advanced stuff and probably not what you are looking for.
I hope this clarifies things a little.
Upvotes: 5