Not in scope: data constructor in Haskell - haskell

Please tell me what is the problem?
data Stack' v = Stack' [v] Int deriving (Show)
...
type StackInt = Stack' Int
main = print(StackInt [1,2,3] 4)
The error i am getting is
Not in scope: data constructor `Stackint'
What is wrong?

It looks to me like you are confusing the concepts of types and constructors, this is a common problem as they live in separate namespaces and are often given the same name. In the Haskell expression
data SomeType = SomeType Int
say, you are actually defining the type SomeType and a constructor SomeType. The type is not a function in the normal sense, but the constructor is. If you asked ghci for the type of SomeType you would get this:
:t SomeType
SomeType :: Int -> SomeType
Now, a type declaration is just a shorthand for a longer type definition, in your case making StackInt a synonym of Stack' Int. But in order to construct a value of this type you still need to use the constructor Stack' (which has type [v] -> Int -> Stack' v). So your code should be
data Stack' v = Stack' [v] Int deriving (Show)
main = print(Stack' [1,2,3] 4)
If you wanted to be sure that the type was Stack' Int then you could add a function
data Stack' v = Stack' [v] Int deriving (Show)
stackInt :: [Int] -> Int -> Stack' Int
stackInt list i = Stack' list i
main = print(stackInt [1,2,3] 4)
EDIT: Not also that I've written stackInt list i = Stack' list i for transparency here, but you can write it more elegantly just as stackInt = Stack'. It is the type constraint that makes sure that you get the right type here.
You could also have both the new function and the type synonym if you wanted, ie
data Stack' v = Stack' [v] Int deriving (Show)
type StackInt = Stack' Int
stackInt :: [Int] -> Int -> StackInt
stackInt list i = Stack' list i
main = print(stackInt [1,2,3] 4)

The name of the constructor is Stack', not StackInt. Creating a type alias using type does not create an alias for the constructors (which wouldn't make sense since there may be many constructors for the type and their names don't have to be related the type name at all).

There is no data constructor called Stackint. Stackint as defined by your type declaration is a type constructor.
The data constructor is, as for Stack', Stack', although thanks to the type synonym it'll have type Int -> Stack' Int instead of a -> Stack' a.

Related

Why can't I match type Int with type a

Haskell Noob here.
An oversimplified case of what I'm trying to do here:
test :: Int -> a
test i = i -- Couldn't match expected type ‘a’ with actual type ‘Int’. ‘a’ is a rigid type variable bound by ...
I don't quite understand why this wouldn't work. I mean, Int is surely included in something of type a.
What I was really trying to achieve is this:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
data EnumType = Enum1 | Enum2 | Enum3
data MyType (a :: EnumType) where
Type1 :: Int -> MyType 'Enum1
Type2 :: String -> MyType 'Enum2
Type3 :: Bool -> MyType 'Enum3
myFunc :: EnumType -> MyType 'Enum1 -> MyType any
myFunc Enum1 t = t -- Can't match type `any` with `Enum1`. any is a rigid type variable bound by ...
myFunc Enum2 _ = Type2 "hi"
myFunc Enum3 _ = Type3 True
What is going on here? Is there a way to work around this or is it just something you can't do?
For the GADT function you want to write, the standard technique is to use singletons. The problem is that values of type EnumType are value-level things, but you want to inform the type system of something. So you need a way to connect types of kind EnumType with values of type EnumType (which itself has kind Type). That's impossible, so we cheat: we connect types x of kind EnumType with values of a new type, SEnumType x, such that the value uniquely determines x. Here's how it looks:
data SEnumType a where
SEnum1 :: SEnumType Enum1
SEnum2 :: SEnumType Enum2
SEnum3 :: SEnumType Enum3
myFunc :: SEnumType a -> MyType Enum1 -> MyType a
myFunc SEnum1 t = t
myFunc SEnum2 _ = Type2 "hi"
myFunc SEnum3 _ = Type3 True
Now the a in the return type MyType a isn't just fabricated out of thin air; it is constrained to be equal to the incoming a from SEnumType, and pattern matching on which SEnumType it is lets you observe whether a is Enum1, Enum2, or Enum3.
Is there a way to work around this or is it just something you can't do?
I'm afraid that it's just "something you can't do". The reason is simple to explain.
When you write a type signature like (to take your first, simpler example)
test :: Int -> a
or, to write it the more literal, expanded form
test :: forall a. Int -> a
You are saying that literally, "for all a", this function can take an Int and return a value of type a. This is important, because calling code has to believe this type signature and therefore be able to do something like this (this isn't realistic code, but imagine a case where you feed the result of test 2 to a function that requires a Char or one of those other types):
test 2 :: Char
test 2 :: [Int]
test 2 :: (Double, [Char])
and so on. Clearly your function can't work with any of these examples - but it has to be able to work with any of them if you give it this type signature. Your code, quite simply, does not fit that type signature. (And nor could any, unless you "cheat" by having eg test x = undefined.)
This shouldn't be a problem though - the compiler is simply protecting you from a mistake, because I'm sure you realise that your code cannot satisfy this type signature. To take your "real" example:
myFunc :: EnumType -> MyType Enum1 -> MyType any
although this produces a compilation error, your code in the function is likely correct, and the problem is the type signature. If you replace it with
myFunc :: EnumType -> MyType Enum1 -> MyType Enum1
then it will compile (barring any further errors, which I've not checked it for), and presumably do what you want. It doesn't look like you actually want to be able to call myFunc and have it produce, say, a MyType Int. (If by any chance you do, I'd suggest you ask a separate question where you elaborate on what you actually need here.)
As was already said, your signature expresses a universal type
myFunc :: ∀ a . EnumType -> MyType 'Enum1 -> MyType a
whereas what you're actually trying to express is an existential type
myFunc :: EnumType -> MyType 'Enum1 -> (∃ a . MyType a)
Haskell doesn't have a feature quite like that, but it does have some way to achieve essentially the same thing.
Both GADTs and the ExistentialTypes extension allow expressing existentials, but you need to define a separate type for them.
data MyDynType where
MyDynWrap :: MyType a -> MyDynType
myFunc :: EnumType -> MyType 'Enum1 -> MyDynType
myFunc Enum1 t = MyDynWrap t
myFunc Enum2 _ = MyDynWrap $ Type2 "hi"
myFunc Enum3 _ = MyDynWrap $ Type3 True
Maybe you don't even need a separate type, but can simply modify MyType to be “dynamic” in the first place.
data MyType = Type1 Int | Type2 String | Type3 Bool
myFunc :: EnumType -> MyType -> MyType
myFunc Enum1 (Type1 i) = Type1 i
myFunc Enum2 _ = Type2 "hi"
myFunc Enum3 _ = Type3 True
existentials can be emulated at the spot, anonymously, by unwrapping a layer of continuation-passing style and then using the dual universal quantifier via the RankNTypes extension.
{-# LANGUAGE RankNTypes #-}
data MyType (a :: EnumType) where ... -- as original
myFunc :: EnumType -> MyType 'Enum1 -> (∀ a . MyType a -> r) -> r
myFunc Enum1 t q = q t
myFunc Enum2 _ q = q (Type2 "hi")
myFunc Enum3 _ q = q (Type3 True)
the GADT function you want to write, the standard technique is to use singletons. The problem is that values of type EnumType are ...

Deriving Eq and Show for an ADT that contains fields that can't have Eq or Show

I'd like to be able to derive Eq and Show for an ADT that contains multiple fields. One of them is a function field. When doing Show, I'd like it to display something bogus, like e.g. "<function>"; when doing Eq, I'd like it to ignore that field. How can I best do this without hand-writing a full instance for Show and Eq?
I don't want to wrap the function field inside a newtype and write my own Eq and Show for that - it would be too bothersome to use like that.
One way you can get proper Eq and Show instances is to, instead of hard-coding that function field, make it a type parameter and provide a function that just “erases” that field. I.e., if you have
data Foo = Foo
{ fooI :: Int
, fooF :: Int -> Int }
you change it to
data Foo' f = Foo
{ _fooI :: Int
, _fooF :: f }
deriving (Eq, Show)
type Foo = Foo' (Int -> Int)
eraseFn :: Foo -> Foo' ()
eraseFn foo = foo{ fooF = () }
Then, Foo will still not be Eq- or Showable (which after all it shouldn't be), but to make a Foo value showable you can just wrap it in eraseFn.
Typically what I do in this circumstance is exactly what you say you don’t want to do, namely, wrap the function in a newtype and provide a Show for that:
data T1
{ f :: X -> Y
, xs :: [String]
, ys :: [Bool]
}
data T2
{ f :: OpaqueFunction X Y
, xs :: [String]
, ys :: [Bool]
}
deriving (Show)
newtype OpaqueFunction a b = OpaqueFunction (a -> b)
instance Show (OpaqueFunction a b) where
show = const "<function>"
If you don’t want to do that, you can instead make the function a type parameter, and substitute it out when Showing the type:
data T3' a
{ f :: a
, xs :: [String]
, ys :: [Bool]
}
deriving (Functor, Show)
newtype T3 = T3 (T3' (X -> Y))
data Opaque = Opaque
instance Show Opaque where
show = const "..."
instance Show T3 where
show (T3 t) = show (Opaque <$ t)
Or I’ll refactor my data type to derive Show only for the parts I want to be Showable by default, and override the other parts:
data T4 = T4
{ f :: X -> Y
, xys :: T4' -- Move the other fields into another type.
}
instance Show T4 where
show (T4 f xys) = "T4 <function> " <> show xys
data T4' = T4'
{ xs :: [String]
, ys :: [Bool]
}
deriving (Show) -- Derive ‘Show’ for the showable fields.
Or if my type is small, I’ll use a newtype instead of data, and derive Show via something like OpaqueFunction:
{-# LANGUAGE DerivingVia #-}
newtype T5 = T5 (X -> Y, [String], [Bool])
deriving (Show) via (OpaqueFunction X Y, [String], [Bool])
You can use the iso-deriving package to do this for data types using lenses if you care about keeping the field names / record accessors.
As for Eq (or Ord), it’s not a good idea to have an instance that equates values that can be observably distinguished in some way, since some code will treat them as identical and other code will not, and now you’re forced to care about stability: in some circumstance where I have a == b, should I pick a or b? This is why substitutability is a law for Eq: forall x y f. (x == y) ==> (f x == f y) if f is a “public” function that upholds the invariants of the type of x and y (although floating-point also violates this). A better choice is something like T4 above, having equality only for the parts of a type that can satisfy the laws, or explicitly using comparison modulo some function at use sites, e.g., comparing someField.
The module Text.Show.Functions in base provides a show instance for functions that displays <function>. To use it, just:
import Text.Show.Functions
It just defines an instance something like:
instance Show (a -> b) where
show _ = "<function>"
Similarly, you can define your own Eq instance:
import Text.Show.Functions
instance Eq (a -> b) where
-- all functions are equal...
-- ...though some are more equal than others
_ == _ = True
data Foo = Foo Int Double (Int -> Int) deriving (Show, Eq)
main = do
print $ Foo 1 2.0 (+1)
print $ Foo 1 2.0 (+1) == Foo 1 2.0 (+2) -- is True
This will be an orphan instance, so you'll get a warning with -Wall.
Obviously, these instances will apply to all functions. You can write instances for a more specialized function type (e.g., only for Int -> String, if that's the type of the function field in your data type), but there is no way to simultaneously (1) use the built-in Eq and Show deriving mechanisms to derive instances for your datatype, (2) not introduce a newtype wrapper for the function field (or some other type polymorphism as mentioned in the other answers), and (3) only have the function instances apply to the function field of your data type and not other function values of the same type.
If you really want to limit applicability of the custom function instances without a newtype wrapper, you'd probably need to build your own generics-based solution, which wouldn't make much sense unless you wanted to do this for a lot of data types. If you go this route, then the Generics.Deriving.Show and Generics.Deriving.Eq modules in generic-deriving provide templates for these instances which could be modified to treat functions specially, allowing you to derive per-datatype instances using some stub instances something like:
instance Show Foo where showsPrec = myGenericShowsPrec
instance Eq Foo where (==) = myGenericEquality
I proposed an idea for adding annotations to fields via fields, that allows operating on behaviour of individual fields.
data A = A
{ a :: Int
, b :: Int
, c :: Int -> Int via Ignore (Int->Int)
}
deriving
stock GHC.Generic
deriving (Eq, Show)
via Generically A -- assuming Eq (Generically A)
-- Show (Generically A)
But this is already possible with the "microsurgery" library, but you might have to write some boilerplate to get it going. Another solution is to write separate behaviour in "sums-of-products style"
data A = A Int Int (Int->Int)
deriving
stock GHC.Generic
deriving
anyclass SOP.Generic
deriving (Eq, Show)
via A <-𝈖-> '[ '[ Int, Int, Ignore (Int->Int) ] ]

The limit set of types with new data like `Tree a`

Exploring and studing type system in Haskell I've found some problems.
1) Let's consider polymorphic type as Binary Tree:
data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Show
And, for example, I want to limit my considerations only with Tree Int, Tree Bool and Tree Char. Of course, I can make a such new type:
data TreeIWant = T1 (Tree Int) | T2 (Tree Bool) | T3 (Tree Char) deriving Show
But could it possible to make new restricted type (for homogeneous trees) in more elegant (and without new tags like T1,T2,T3) way (perhaps with some advanced type extensions)?
2) Second question is about trees with heterogeneous values. I can do them with usual Haskell, i.e. I can do the new helping type, contained tagged heterogeneous values:
data HeteroValues = H1 Int | H2 Bool | H3 Char deriving Show
and then make tree with values of this type:
type TreeH = Tree HeteroValues
But could it possible to make new type (for heterogeneous trees) in more elegant (and without new tags like H1,H2,H3) way (perhaps with some advanced type extensions)?
I know about heterogeneous list, perhaps it is the same question?
For question #2, it's easy to construct a "restricted" heterogeneous type without explicit tags using a GADT and a type class:
{-# LANGUAGE GADTs #-}
data Thing where
T :: THING a => a -> Thing
class THING a
Now, declare THING instances for the the things you want to allow:
instance THING Int
instance THING Bool
instance THING Char
and you can create Things and lists (or trees) of Things:
> t1 = T 'a' -- Char is okay
> t2 = T "hello" -- but String is not
... type error ...
> tl = [T (42 :: Int), T True, T 'x']
> tt = Branch (Leaf (T 'x')) (Leaf (T False))
>
In terms of the type names in your question, you have:
type HeteroValues = Thing
type TreeH = Tree Thing
You can use the same type class with a new GADT for question #1:
data ThingTree where
TT :: THING a => Tree a -> ThingTree
and you have:
type TreeIWant = ThingTree
and you can do:
> tt1 = TT $ Branch (Leaf 'x') (Leaf 'y')
> tt2 = TT $ Branch (Leaf 'x') (Leaf False)
... type error ...
>
That's all well and good, until you try to use any of the values you've constructed. For example, if you wanted to write a function to extract a Bool from a possibly boolish Thing:
maybeBool :: Thing -> Maybe Bool
maybeBool (T x) = ...
you'd find yourself stuck here. Without a "tag" of some kind, there's no way of determining if x is a Bool, Int, or Char.
Actually, though, you do have an implicit tag available, namely the THING type class dictionary for x. So, you can write:
maybeBool :: Thing -> Maybe Bool
maybeBool (T x) = maybeBool' x
and then implement maybeBool' in your type class:
class THING a where
maybeBool' :: a -> Maybe Bool
instance THING Int where
maybeBool' _ = Nothing
instance THING Bool where
maybeBool' = Just
instance THING Char where
maybeBool' _ = Nothing
and you're golden!
Of course, if you'd used explicit tags:
data Thing = T_Int Int | T_Bool Bool | T_Char Char
then you could skip the type class and write:
maybeBool :: Thing -> Maybe Bool
maybeBool (T_Bool x) = Just x
maybeBool _ = Nothing
In the end, it turns out that the best Haskell representation of an algebraic sum of three types is just an algebraic sum of three types:
data Thing = T_Int Int | T_Bool Bool | T_Char Char
Trying to avoid the need for explicit tags will probably lead to a lot of inelegant boilerplate elsewhere.
Update: As #DanielWagner pointed out in a comment, you can use Data.Typeable in place of this boilerplate (effectively, have GHC generate a lot of boilerplate for you), so you can write:
import Data.Typeable
data Thing where
T :: THING a => a -> Thing
class Typeable a => THING a
instance THING Int
instance THING Bool
instance THING Char
maybeBool :: Thing -> Maybe Bool
maybeBool = cast
This perhaps seems "elegant" at first, but if you try this approach in real code, I think you'll regret losing the ability to pattern match on Thing constructors at usage sites (and so having to substitute chains of casts and/or comparisons of TypeReps).

differences: GADT, data family, data family that is a GADT

What/why are the differences between those three? Is a GADT (and regular data types) just a shorthand for a data family? Specifically what's the difference between:
data GADT a where
MkGADT :: Int -> GADT Int
data family FGADT a
data instance FGADT a where -- note not FGADT Int
MkFGADT :: Int -> FGADT Int
data family DF a
data instance DF Int where -- using GADT syntax, but not a GADT
MkDF :: Int -> DF Int
(Are those examples over-simplified, so I'm not seeing the subtleties of the differences?)
Data families are extensible, but GADTs are not. OTOH data family instances must not overlap. So I couldn't declare another instance/any other constructors for FGADT; just like I can't declare any other constructors for GADT. I can declare other instances for DF.
With pattern matching on those constructors, the rhs of the equation does 'know' that the payload is Int.
For class instances (I was surprised to find) I can write overlapping instances to consume GADTs:
instance C (GADT a) ...
instance {-# OVERLAPPING #-} C (GADT Int) ...
and similarly for (FGADT a), (FGADT Int). But not for (DF a): it must be for (DF Int) -- that makes sense; there's no data instance DF a, and if there were it would overlap.
ADDIT: to clarify #kabuhr's answer (thank you)
contrary to what I think you're claiming in part of your question, for a plain data family, matching on a constructor does not perform any inference
These types are tricky, so I expect I'd need explicit signatures to work with them. In that case the plain data family is easiest
inferDF (MkDF x) = x -- works without a signature
The inferred type inferDF :: DF Int -> Int makes sense. Giving it a signature inferDF :: DF a -> a doesn't make sense: there is no declaration for a data instance DF a .... Similarly with foodouble :: Foo Char a -> a there is no data instance Foo Char a ....
GADTs are awkward, I already know. So neither of these work without an explicit signature
inferGADT (MkGADT x) = x
inferFGADT (MkFGADT x) = x
Mysterious "untouchable" message, as you say. What I meant in my "matching on those constructors" comment was: the compiler 'knows' on rhs of an equation that the payload is Int (for all three constructors), so you'd better get any signatures consistent with that.
Then I'm thinking data GADT a where ... is as if data instance GADT a where .... I can give a signature inferGADT :: GADT a -> a or inferGADT :: GADT Int -> Int (likewise for inferFGADT). That makes sense: there is a data instance GADT a ... or I can give a signature at a more specific type.
So in some ways data families are generalisations of GADTs. I also see as you say
So, in some ways, GADTs are generalizations of data families.
Hmm. (The reason behind the question is that GHC Haskell has got to the stage of feature bloat: there's too many similar-but-different extensions. I was trying to prune it down to a smaller number of underlying abstractions. Then #HTNW's approach of explaining in terms of yet further extensions is opposite to what would help a learner. IMO existentials in data types should be chucked out: use GADTs instead. PatternSynonyms should be explained in terms of data types and mapping functions between them, not the other way round. Oh, and there's some DataKinds stuff, which I skipped over on first reading.)
As a start, you should think of a data family as a collection of independent ADTs that happen to be indexed by a type, while a GADT is a single data type with an inferrable type parameter where constraints on that parameter (typically, equality constraints like a ~ Int) can be brought into scope by pattern matching.
This means that the biggest difference is that, contrary to what I think you're claiming in part of your question, for a plain data family, matching on a constructor does not perform any inference on the type parameter. In particular, this typechecks:
inferGADT :: GADT a -> a
inferGADT (MkGADT n) = n
but this does not:
inferDF :: DF a -> a
inferDF (MkDF n) = n
and without type signatures, the first would fail to type check (with a mysterious "untouchable" message) while the second would be inferred as DF Int -> Int.
The situation becomes quite a bit more confusing for something like your FGADT type that combines data families with GADTs, and I confess I haven't really thought about how this works in detail. But, as an interesting example, consider:
data family Foo a b
data instance Foo Int a where
Bar :: Double -> Foo Int Double
Baz :: String -> Foo Int String
data instance Foo Char Double where
Quux :: Double -> Foo Char Double
data instance Foo Char String where
Zlorf :: String -> Foo Char String
In this case, Foo Int a is a GADT with an inferrable a parameter:
fooint :: Foo Int a -> a
fooint (Bar x) = x + 1.0
fooint (Baz x) = x ++ "ish"
but Foo Char a is just a collection of separate ADTs, so this won't typecheck:
foodouble :: Foo Char a -> a
foodouble (Quux x) = x
for the same reason inferDF won't typecheck above.
Now, getting back to your plain DF and GADT types, you can largely emulate DFs just using GADTs. For example, if you have a DF:
data family MyDF a
data instance MyDF Int where
IntLit :: Int -> MyDF Int
IntAdd :: MyDF Int -> MyDF Int -> MyDF Int
data instance MyDF Bool where
Positive :: MyDF Int -> MyDF Bool
you can write it as a GADT just by writing separate blocks of constructors:
data MyGADT a where
-- MyGADT Int
IntLit' :: Int -> MyGADT Int
IntAdd' :: MyGADT Int -> MyGADT Int -> MyGADT Int
-- MyGADT Bool
Positive' :: MyGADT Int -> MyGADT Bool
So, in some ways, GADTs are generalizations of data families. However, a major use case for data families is defining associated data types for classes:
class MyClass a where
data family MyRep a
instance MyClass Int where
data instance MyRep Int = ...
instance MyClass String where
data instance MyRep String = ...
where the "open" nature of data families is needed (and where the pattern-based inference methods of GADTs aren't helpful).
I think the difference becomes clear if we use PatternSynonyms-style type signatures for data constructors. Lets start with Haskell 98
data D a = D a a
You get a pattern type:
pattern D :: forall a. a -> a -> D a
it can be read in two directions. D, in "forward" or expression contexts, says, "forall a, you can give me 2 as and I'll give you a D a". "Backwards", as a pattern, it says, "forall a, you can give me a D a and I'll give you 2 as".
Now, the things you write in a GADT definition are not pattern types. What are they? Lies. Lies lies lies. Give them attention only insofar as the alternative is writing them out manually with ExistentialQuantification. Let's use this one
data GD a where
GD :: Int -> GD Int
You get
-- vv ignore
pattern GD :: forall a. () => (a ~ Int) => Int -> GD a
This says: forall a, you can give me a GD a, and I can give you a proof that a ~ Int, plus an Int.
Important observation: The return/match type of a GADT constructor is always the "data type head". I defined data GD a where ...; I got GD :: forall a. ... GD a. This is also true for Haskell 98 constructors, and also data family constructors, though it's a bit more subtle.
If I have a GD a, and I don't know what a is, I can pass into GD anyway, even though I wrote GD :: Int -> GD Int, which seems to say I can only match it with GD Ints. This is why I say GADT constructors lie. The pattern type never lies. It clearly states that, forall a, I can match a GD a with the GD constructor and get evidence for a ~ Int and a value of Int.
Ok, data familys. Lets not mix them with GADTs yet.
data Nat = Z | S Nat
data Vect (n :: Nat) (a :: Type) :: Type where
VNil :: Vect Z a
VCons :: a -> Vect n a -> Vect (S n) a -- try finding the pattern types for these btw
data family Rect (ns :: [Nat]) (a :: Type) :: Type
newtype instance Rect '[] a = RectNil a
newtype instance Rect (n : ns) a = RectCons (Vect n (Rect ns a))
There are actually two data type heads now. As #K.A.Buhr says, the different data instances act like different data types that just happen to share a name. The pattern types are
pattern RectNil :: forall a. a -> Rect '[] a
pattern RectCons :: forall n ns a. Vect n (Rect ns a) -> Rect (n : ns) a
If I have a Rect ns a, and I don't know what ns is, I cannot match on it. RectNil only takes Rect '[] as, RectCons only takes Rect (n : ns) as. You might ask: "why would I want a reduction in power?" #KABuhr has given one: GADTs are closed (and for good reason; stay tuned), families are open. This doesn't hold in Rect's case, as these instances already fill up the entire [Nat] * Type space. The reason is actually newtype.
Here's a GADT RectG:
data RectG :: [Nat] -> Type -> Type where
RectGN :: a -> RectG '[] a
RectGC :: Vect n (RectG ns a) -> RectG (n : ns) a
I get
-- it's fine if you don't get these
pattern RectGN :: forall ns a. () => (ns ~ '[]) => a -> RectG ns a
pattern RectGC :: forall ns' a. forall n ns. (ns' ~ (n : ns)) =>
Vect n (RectG ns a) -> RectG ns' a
-- just note that they both have the same matched type
-- which means there needs to be a runtime distinguishment
If I have a RectG ns a and don't know what ns is, I can still match on it just fine. The compiler has to preserve this information with a data constructor. So, if I had a RectG [1000, 1000] Int, I would incur an overhead of one million RectGN constructors that all "preserve" the same "information". Rect [1000, 1000] Int is fine, though, as I do not have the ability to match and tell whether a Rect is RectNil or RectCons. This allows the constructor to be newtype, as it holds no information. I would instead use a different GADT, somewhat like
data SingListNat :: [Nat] -> Type where
SLNN :: SingListNat '[]
SLNCZ :: SingListNat ns -> SingListNat (Z : ns)
SLNCS :: SingListNat (n : ns) -> SingListNat (S n : ns)
that stores the dimensions of a Rect in O(sum ns) space instead of O(product ns) space (I think those are right). This is also why GADTs are closed and families are open. A GADT is just like a normal data type except it has equality evidence and existentials. It doesn't make sense to add constructors to a GADT any more than it makes sense to add constructors to a Haskell 98 type, because any code that doesn't know about one of the constructors is in for a very bad time. It's fine for families though, because, as you noticed, once you define a branch of a family, you cannot add more constructors in that branch. Once you know what branch you're in, you know the constructors, and no one can break that. You're not allowed to use any constructors if you don't know which branch to use.
Your examples don't really mix GADTs and data families. Pattern types are nifty in that they normalize away superficial differences in data definitions, so let's take a look.
data family FGADT a
data instance FGADT a where
MkFGADT :: Int -> FGADT Int
Gives you
pattern MkFGADT :: forall a. () => (a ~ Int) => Int -> FGADT a
-- no different from a GADT; data family does nothing
But
data family DF a
data instance DF Int where
MkDF :: Int -> DF Int
gives
pattern MkDF :: Int -> DF Int
-- GADT syntax did nothing
Here's a proper mixing
data family Map k :: Type -> Type
data instance Map Word8 :: Type -> Type where
MW8BitSet :: BitSet8 -> Map Word8 Bool
MW8General :: GeneralMap Word8 a -> Map Word8 a
Which gives patterns
pattern MW8BitSet :: forall a. () => (a ~ Bool) => BitSet8 -> Map Word8 a
pattern MW8General :: forall a. GeneralMap Word8 a -> Map Word8 a
If I have a Map k v and I don't know what k is, I can't match it against MW8General or MW8BitSet, because those only want Map Word8s. This is the data family's influence. If I have a Map Word8 v and I don't know what v is, matching on the constructors can reveal to me whether it's known to be Bool or is something else.

How to tell whether variable is a certain data in Haskell?

Edit: This class instance of QWhere fails when it's passed input like this: >qWhere fly john even though fly is type Argument -> Argument -> Predicate and john is type Argument.
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
data Argument = Argument { ttype :: Type, value :: String } deriving (Show, Eq)
data Predicate = Predicate { lemma :: String, arguments :: [Argument] } deriving (Show, Eq)
class Fly a b where
fly :: a -> b -> Predicate
instance Fly Argument Argument where
fly x y = Predicate { lemma = "fly", arguments = [x, y] }
instance Fly Argument Predicate where
fly x y = Predicate { lemma = "fly", arguments = [x, arguments y !! 0] }
class QWhere a b where
qWhere :: a -> b -> String
instance QWhere (Argument -> Argument -> Predicate) Argument where
qWhere x y = "hi"
This is the output from the ghci:
No instance for (QWhere (a0 -> b0 -> Predicate) Argument)
arising from a use of ‘qWhere’
The type variables ‘a0’, ‘b0’ are ambiguous
Note: there is a potential instance available:
instance QWhere (Argument -> Argument -> Predicate) Argument
-- Defined at new_context.hs:116:10
In the expression: qWhere fly john
In an equation for ‘it’: it = qWhere fly john
No instance for (Fly a0 b0) arising from a use of ‘fly’
The type variables ‘a0’, ‘b0’ are ambiguous
Note: there are several potential instances:
instance Fly Argument Predicate
-- Defined at new_context.hs:110:10
instance Fly Argument Argument
-- Defined at new_context.hs:107:10
In the first argument of ‘qWhere’, namely ‘fly’
In the expression: qWhere fly john
In an equation for ‘it’: it = qWhere fly john
These questions are relevant, but none of the answers have solved my problem.
(1) Checking for a particular data constructor
(2) Test if Haskell variable matches user-defined data type option
And some internet sources which should address this question but I could not find the solution from:
(3) https://www.haskell.org/haskellwiki/Determining_the_type_of_an_expression
(4) http://okmij.org/ftp/Haskell/typeEQ.html
My problem: I have two Haskell data types defined. I am given an input and I need to determine if it belongs to data type A or data type B.
Here is the data types definition:
data Argument = Argument { ttype :: Type, value :: String } deriving (Show, Eq)
data Predicate = Predicate { lemma :: String, arguments :: [Argument] } deriving (Show, Eq)
I need a function which returns true/false if a variable is a data type Argument or Predicate.
I attempted to follow the answers of both SO questions, but only got complaints from the ghci compiler:
--checks if a variable is of data type Argument
--this does not compile (from question (2))
isArgument :: a -> Bool
isArgument (Argument _) = True
isArgument _ = False
--from question (1), also fails
isArgument :: a -> String
isArgument value =
case token of
Argument arg -> "is argument"
Predicate p -> "is predicate"
The sort of dynamic typing you are trying to do is very rarely used in Haskell. If you want to write functions that can take values of both Predicate and Argument there are at least two idiomatic ways depending on your exact use-case.
The first is to overload the function using type-classes. E.g.
class IsArgument a where
isArgument :: a -> Bool
instance IsArgument Argument where
isArgument _ = True
instance IsArgument Predicate where
isArgument _ = False
The second is to use some sum-type such as Either Predicate Argument or a custom sum-type such as:
data Expr = ArgumentExpr Argument | PredicateExpr Predicate
isArgument :: Expr -> Bool
isArgument (ArgumentExpr _) = True
isArgument _ = False
You can also make Argument and Predicate constructors of the same type, but then of course you lose the type safety of treating them as separate types. You can circumvent this by using a GADT and tagging the constructors with a phantom type but this gets into the slightly more advanced type extensions that GHC offers:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE StandaloneDeriving #-}
data ExprType = Argument | Predicate
data Expr t where
ArgumentExpr :: { ttype :: Type, value :: String } -> Expr Argument
PredicateExpr :: { lemma :: String, arguments :: [Expr Argument] } -> Expr Predicate
deriving instance Show (Expr t)
deriving instance Eq (Expr t)
isArgument :: Expr t -> Bool
isArgument (ArgumentExpr {}) = True
isArgument _ = False
Now arguments and predicates are constructors of the same type but you can limit the values to a specific constructor by using the type parameter as is done in arguments :: [Expr Argument] but you can also just accept any expression using the type Expr t as in isArgument.
If you really really need run-time polymorphism, it can be achieved using the Typeable type-class which enables you to get runtime type information and do type-casts on opaque, generic types.
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Typeable
data Argument = Argument { ttype :: Type, value :: String } deriving (Show, Eq, Typeable)
data Predicate = Predicate { lemma :: String, arguments :: [Argument] } deriving (Show, Eq, Typeable)
isArgument :: Typeable a => a -> Bool
isArgument a = case cast a of
Just (Argument {}) -> True
_ -> False
The function cast tries to convert any Typeable a => a value into some known type and returns a Just value if the type-cast succeeds and Nothing if it fails.
You can do what you want by making Argument and Predicate part of the same type....
data LogicElement = Argument { ttype :: Type, value :: String } |
Predicate { lemma :: String, arguments :: [LogicElement] } deriving (Show, Eq)
While it is possible to define a function of type (a->Bool), it is unusual, and generally implies that the value being input will be ignored (ie- how can you do anything to something if you don't even know what it is? You pretty much can only apply other (a->b) functions on it).
In the particular example, you compiler will complain at the following
isArgument (Argument _) = True
because the pattern implicitly implies that the input argument must be type Argument, whereas the signature you gave was undefined type a.
When you say that isArgument has type a -> Bool, you're saying that it can take any, or rather every possible a, not just certain ones. There are a few solutions to this, though. My preference would be that for simple alternatives, just use Either:
import Data.Either
isArgument :: Either Argument Predicate -> Bool
isArgument = isLeft
Or
-- Note the use of {} instead of _, the {} expands to all fields in a record
-- the _ only would have taken the place of the ttype field, although you could have
-- (Argument _ _) to capture both fields of the Argument constructor
isArgument :: Either Argument Predicate -> Bool
isArgument (Left (Argument {})) = True
isArgument _ = False
Although, the only use of this sort of function would be when you aren't sure which data type you have, and a value in Haskell can't be ambiguously typed. It would be equivalent to if you had in Java/C/C++/C# something like
if (some_condition) {
x = "a string";
} else {
x = 5;
}
These are statically typed languages, a variable can't take on values of two different types. The same holds in Haskell. If you wanted to give a type to a variable that could take on two different values, you'd have to write a container for it. The Either container in Haskell is pre-defined for this purpose.

Resources