Can I specify the a in a phantom type to be limited to a sum type?
How can I create Answers of type Gender, Race, or Age? These should be possible: λ> Answer Male λ> Answer White λ> Answer Black λ> Answer 28 Others such as using a string should not be possible: λ> Answer "a string" -- should throw type error {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneDeriving #-} module Tutorial where data Gender = Male | Female deriving (Show) data Race = White | Black deriving (Show) type Age = Int data Answer a where Answer :: Gender -> Answer Gender deriving instance Show (Answer w) -- λ> -- This is pretty useful and accepts Answers with the Gender -- λ> Answer Male -- Answer Male -- λ> :t Answer Male -- Answer Male :: Answer Gender -- λ> -- how do I also accept Race and Age? -- below I try to sort out how to use type families (unsuccessfully) before bed -- type family Answer :: * -- type instance Answer Gender = Answer Gender
On Fri, May 15, 2015 at 01:47:49AM -0500, Cody Goodman wrote:
How can I create Answers of type Gender, Race, or Age?
These should be possible:
λ> Answer Male λ> Answer White λ> Answer Black λ> Answer 28
Others such as using a string should not be possible:
λ> Answer "a string" -- should throw type error
It would probably help if you tell us why precisely you want this, and in particular why data Answer = AnswerGender Gender | AnswerRace Race | AnswerAge Int is not satisfactory. Tom
You can do this, although you still need a datastructure that allows you to use the contained type: {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeSynonymInstances #-} module Tutorial where data Gender = Male | Female deriving (Show) data Race = White | Black deriving (Show) type Age = Int data Answer a where Answer :: RacistAgistSexist a => a -> Answer a deriving instance Show w => Show (Answer w) data GenderRaceAge = Gender Gender | Race Race | Age Age class RacistAgistSexist a where genderRaceAge :: a -> GenderRaceAge instance RacistAgistSexist Gender where genderRaceAge = Gender instance RacistAgistSexist Race where genderRaceAge = Race instance RacistAgistSexist Age where genderRaceAge = Age -- You can use genderRaceAge to get a GenderRaceAge out of the contained type if you don't know 'a' On 15 May 2015 at 08:51, Tom Ellis < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> wrote:
On Fri, May 15, 2015 at 01:47:49AM -0500, Cody Goodman wrote:
How can I create Answers of type Gender, Race, or Age?
These should be possible:
λ> Answer Male λ> Answer White λ> Answer Black λ> Answer 28
Others such as using a string should not be possible:
λ> Answer "a string" -- should throw type error
It would probably help if you tell us why precisely you want this, and in particular why
data Answer = AnswerGender Gender | AnswerRace Race | AnswerAge Int
is not satisfactory.
Tom
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Tom, I'm trying to make a well-typed API to Question/Answers on medical forms. The questions will be lined with a specific code, so I want to enforce that certain codes can only contain certain types of answers. Andras, thanks. I'll give that a try later today and let you know how it works. On Fri, May 15, 2015 at 4:12 AM, Andras Slemmer <0slemi0@gmail.com> wrote:
You can do this, although you still need a datastructure that allows you to use the contained type:
{-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeSynonymInstances #-} module Tutorial where
data Gender = Male | Female deriving (Show)
data Race = White | Black deriving (Show)
type Age = Int
data Answer a where Answer :: RacistAgistSexist a => a -> Answer a
deriving instance Show w => Show (Answer w)
data GenderRaceAge = Gender Gender | Race Race | Age Age
class RacistAgistSexist a where genderRaceAge :: a -> GenderRaceAge instance RacistAgistSexist Gender where genderRaceAge = Gender instance RacistAgistSexist Race where genderRaceAge = Race instance RacistAgistSexist Age where genderRaceAge = Age
-- You can use genderRaceAge to get a GenderRaceAge out of the contained type if you don't know 'a'
On 15 May 2015 at 08:51, Tom Ellis <tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> wrote:
On Fri, May 15, 2015 at 01:47:49AM -0500, Cody Goodman wrote:
How can I create Answers of type Gender, Race, or Age?
These should be possible:
λ> Answer Male λ> Answer White λ> Answer Black λ> Answer 28
Others such as using a string should not be possible:
λ> Answer "a string" -- should throw type error
It would probably help if you tell us why precisely you want this, and in particular why
data Answer = AnswerGender Gender | AnswerRace Race | AnswerAge Int
is not satisfactory.
Tom
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Read the paper "Data types a la carte"[1], and check out the compdata[2] library for an implementation. The idea is that instead of making a big union type like: data Answers = SexAnswer | AgeAnswer | etc... you make data Sex = M | F | etc newtype Age = Age Int and then you construct functions that accept sum types: ageOrSex :: Age :+: Sex -> m Bool ... A single type class, called :<: in the paper, handles dispatching from sums the underlying values to sums. [1]: http://www.cs.ru.nl/~W.Swierstra/Publications/DataTypesALaCarte.pdf [2: https://hackage.haskell.org/package/compdata On Fri, May 15, 2015 at 5:39 AM, Cody Goodman <codygman.consulting@gmail.com
wrote:
Tom, I'm trying to make a well-typed API to Question/Answers on medical forms. The questions will be lined with a specific code, so I want to enforce that certain codes can only contain certain types of answers.
Andras, thanks. I'll give that a try later today and let you know how it works.
On Fri, May 15, 2015 at 4:12 AM, Andras Slemmer <0slemi0@gmail.com> wrote:
You can do this, although you still need a datastructure that allows you to use the contained type:
{-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeSynonymInstances #-} module Tutorial where
data Gender = Male | Female deriving (Show)
data Race = White | Black deriving (Show)
type Age = Int
data Answer a where Answer :: RacistAgistSexist a => a -> Answer a
deriving instance Show w => Show (Answer w)
data GenderRaceAge = Gender Gender | Race Race | Age Age
class RacistAgistSexist a where genderRaceAge :: a -> GenderRaceAge instance RacistAgistSexist Gender where genderRaceAge = Gender instance RacistAgistSexist Race where genderRaceAge = Race instance RacistAgistSexist Age where genderRaceAge = Age
-- You can use genderRaceAge to get a GenderRaceAge out of the contained type if you don't know 'a'
On 15 May 2015 at 08:51, Tom Ellis <tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> wrote:
On Fri, May 15, 2015 at 01:47:49AM -0500, Cody Goodman wrote:
How can I create Answers of type Gender, Race, or Age?
These should be possible:
λ> Answer Male λ> Answer White λ> Answer Black λ> Answer 28
Others such as using a string should not be possible:
λ> Answer "a string" -- should throw type error
It would probably help if you tell us why precisely you want this, and
in
particular why
data Answer = AnswerGender Gender | AnswerRace Race | AnswerAge Int
is not satisfactory.
Tom
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
participants (4)
-
Alexander Solla -
Andras Slemmer -
Cody Goodman -
Tom Ellis