Why can't I match type Int with type a - haskell

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 ...

Related

Parameterized Types in Haskell

Why do types in Haskell have to be explicitly parameterized in the type constructor parameter?
For example:
data Maybe a = Nothing | Just a
Here a has to be specified with the type. Why can't it be specified only in the constructor?
data Maybe = Nothing | Just a
Why did they make this choice from a design point of view? Is one better than the other?
I do understand that first is more strongly typed than the second, but there isn't even an option for the second one.
Edit :
Example function
data Maybe = Just a | Nothing
div :: (Int -> Int -> Maybe)
div a b
| b == 0 = Nothing
| otherwise = Just (a / b)
It would probably clear things up to use GADT notation, since the standard notation kind of mangles together the type- and value-level languages.
The standard Maybe type looks thus as a GADT:
{-# LANGUAGE GADTs #-}
data Maybe a where
Nothing :: Maybe a
Just :: a -> Maybe a
The “un-parameterised” version is also possible:
data EMaybe where
ENothing :: EMaybe
EJust :: a -> EMaybe
(as Joseph Sible commented, this is called an existential type). And now you can define
foo :: Maybe Int
foo = Just 37
foo' :: EMaybe
foo' = EJust 37
Great, so why don't we just use EMaybe always?
Well, the problem is when you want to use such a value. With Maybe it's fine, you have full control of the contained type:
bhrar :: Maybe Int -> String
bhrar Nothing = "No number 😞"
bhrar (Just i)
| i<0 = "Negative 😖"
| otherwise = replicate i '😌'
But what can you do with a value of type EMaybe? Not much, it turns out, because EJust contains a value of some unknown type. So whatever you try to use the value for, will be a type error, because the compiler has no way to confirm it's actually the right type.
bhrar :: EMaybe -> String
bhrar' (EJust i) = replicate i '😌'
=====> Error couldn't match expected type Int with a
If a variable is not reflected in the return type it is considered existential. This is possible to define data ExMaybe = ExNothing | forall a. ExJust a but the argument to ExJust is completely useless. ExJust True and ExJust () both have type ExMaybe and are indistinguisable from the type system's perspective.
Here is the GADT syntax for both the original Maybe and the existential ExMaybe
{-# Language GADTs #-}
{-# Language LambdaCase #-}
{-# Language PolyKinds #-}
{-# Language ScopedTypeVariables #-}
{-# Language StandaloneKindSignatures #-}
{-# Language TypeApplications #-}
import Data.Kind (Type)
import Prelude hiding (Maybe(..))
type Maybe :: Type -> Type
data Maybe a where
Nothing :: Maybe a
Just :: a -> Maybe a
type ExMaybe :: Type
data ExMaybe where
ExNothing :: ExMaybe
ExJust :: a -> ExMaybe
You're question is like asking why a function f x = .. needs to specify its argument, there is the option of making the type argument invisible but this is very odd but the argument is still there even if invisible.
-- >> :t JUST
-- JUST :: a -> MAYBE
-- >> :t JUST 'a'
-- JUST 'a' :: MAYBE
type MAYBE :: forall (a :: Type). Type
data MAYBE where
NOTHING :: MAYBE #a
JUST :: a -> MAYBE #a
mAYBE :: b -> (a -> b) -> MAYBE #a -> b
mAYBE nOTHING jUST = \case
NOTHING -> nOTHING
JUST a -> jUST a
Having explicit type parameters makes it much more expressive. You lose so much information without it. For example, how would you write the type of map? Or functors in general?
map :: (a -> b) -> [a] -> [b]
This version says almost nothing about what’s going on
map :: (a -> b) -> [] -> []
Or even worse, head:
head :: [] -> a
Now we suddenly have access to unsafe coerce and zero type safety at all.
unsafeCoerce :: a -> b
unsafeCoerce x = head [x]
But we don’t just lose safety, we also lose the ability to do some things. For example if we want to read something into a list or Maybe, we can no longer specify what kind of list we want.
read :: Read a => a
example :: [Int] -> String
main = do
xs <- getLine
putStringLine (example xs)
This program would be impossible to write without lists having an explicit type parameter. (Or rather, read would be unable to have different implementations for different list types, since content type is now opaque)
It is however, as was mentioned by others, still possible to define a similar type by using the ExistentialQuantification extension. But in those cases you are very limited in how you can use those data types, since you cannot know what they contain.

Haskell: How to write a type of function from a specific type to any type?

In Scala, I could write the following trait:
trait Consumer[A] {
def apply(a: A): Unit
}
And scala would convert whatever I want to Unit, i.e., it would discard the type. Equivalently, I could have said that apply returns Any and ignore the result.
However, in Haskell, if I defined the type as type Consumer = a -> IO (), I wouldn't be able to pass an Int -> IO Int function, as Int isn't ().
There are two ways I know of solving this issue, but none are satisfactory:
Use Data.Functor.void at the call site to manual change IO a to IO (). This is annoying as an API user.
define type Consumer a b = a -> IO b, but then every time I would want to use Consumer in a signature, I would have to carry the useless type b.
Is there any way to define the Consumer type as a function from a to "IO Any"? As far as I know, Haskell does not support something like exists x. a -> IO x.
Using forall results in the opposite of what I want, e.g.,
type Consumer = forall b. a -> IO b
foo :: Int -> IO Int
foo = undefined
bar :: Consumer Int
bar = foo
results in the error:
• Couldn't match type ‘b’ with ‘Int’
‘b’ is a rigid type variable bound by
the type signature for:
bar :: Consumer Int
Expected type: Int -> IO b
Actual type: Int -> IO Int
• In the expression: foo
In an equation for ‘bar’: bar = foo
• Relevant bindings include
bar :: Int -> IO b
Note that I specifically want Consumer to a be type alias, and not a data constructor, as is described here: Haskell function returning existential type. I wouldn't mind if Consumer were a class if anyone knows how to make that work.
To get an existentially-quantified type in Haskell, you need to write down a data declaration (as opposed to a newtype declaration or a type alias declaration, like you used.).
Here's a Consumer type that fits your purposes:
{-# LANGUAGE ExistentialQuantification #-}
data Consumer input = forall output. Consumer { runDiscardingOutput :: input -> IO output }
And, analogously, here is what your example would look like with the new type:
f :: Int -> IO Int
f = undefined
g :: Consumer Int
g = Consumer f
This doesn't really avoid your concerns about client code needing an extra call, though. (I mean, this is no better than exporting a consumer = Data.Functor.void binding from your library.) Also, it complicates how clients will be able to use a consumer, too:
consumer :: Consumer Int
consumer = Consumer (\x -> return [x])
{- This doesn't typecheck -}
main1 :: IO ()
main1 = runIgnoringOutput consumer 4
{- This doesn't typecheck (!!!) -}
main2 :: IO ()
main2 = void (runIgnoringOutput consumer 4)
{- Only this typechecks :( -}
main3 :: IO ()
main3 =
case consumer of
Consumer f -> Data.Functor.void (f 4)
So it would probably make sense to have a apply function in your library that did the dirty work, just as there was an apply function in the Scala library.
apply :: Consumer a -> a -> IO ()
apply (Consumer f) x = void (f x)
I wouldn't mind if Consumer were a class if anyone knows how to make that work.
You can simulate existential types for classes with an associated type family.
But Haskell doesn't allow ambiguous types in classes without using something like a GADT existential wrapper, so you would still have the type information there somewhere.
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}
class Consumer c a where
type Output c
consume :: c -> a -> IO (Output c)
c is necessary here to allow for the reconstruction of the type of Output c, so it is not strictly an existential. But you can now write
{-# LANGUAGE FlexibleInstances, InstanceSigs #-}
instance Consumer (a -> IO b) a where
type Output (a -> IO b) = b
consume :: (a -> IO b) -> a -> IO b
consume = id
This may not fit your use case, because there will not be a type signature that can express Consumer a in a truly existential way. But it is possible to write
... :: (Consumer c a) => c -> ...
(You could also make use of FunctionalDependencies here to clarify the class somewhat.)

Is this use of GADTs fully equivalent to existential types?

Existentially quantified data constructors like
data Foo = forall a. MkFoo a (a -> Bool)
| Nil
can be easily translated to GADTs:
data Foo where
MkFoo :: a -> (a -> Bool) -> Foo
Nil :: Foo
Are there any differences between them: code which compiles with one but not another, or gives different results?
They are nearly equivalent, albeit not completely so, depending on which extensions you turn on.
First of all, note that you don't need to enable the GADTs extension to use the data .. where syntax for existential types. It suffices to enable the following lesser extensions.
{-# LANGUAGE GADTSyntax #-}
{-# LANGUAGE ExistentialQuantification #-}
With these extensions, you can compile
data U where
U :: a -> (a -> String) -> U
foo :: U -> String
foo (U x f) = f x
g x = let h y = const y x
in (h True, h 'a')
The above code also compiles if we replace the extensions and the type definition with
{-# LANGUAGE ExistentialQuantification #-}
data U = forall a . U a (a -> String)
The above code, however, does not compile with the GADTs extension turned on! This is because GADTs also turns on the MonoLocalBinds extension, which prevents the above definition of g to compile. This is because the latter extension prevents h to receive a polymorphic type.
From the documentation:
Notice that GADT-style syntax generalises existential types (Existentially quantified data constructors). For example, these two declarations are equivalent:
data Foo = forall a. MkFoo a (a -> Bool)
data Foo' where { MKFoo :: a -> (a->Bool) -> Foo' }
(emphasis on the word equivalent)
The latter isn't actually a GADT - it's an existentially quantified data type declared with GADT syntax. As such, it is identical to the former.
The reason it's not a GADT is that there is no type variable that gets refined based on the choice of constructor. That's the key new functionality added by GADTs. If you have a GADT like this:
data Foo a where
StringFoo :: String -> Foo String
IntFoo :: Int -> Foo Int
Then pattern-matching on each constructor reveals additional information that can be used inside the matching clause. For instance:
deconstructFoo :: Foo a -> a
deconstructFoo (StringFoo s) = "Hello! " ++ s ++ " is a String!"
deconstructFoo (IntFoo i) = i * 3 + 1
Notice that something very interesting is happening there, from the point of view of the type system. deconstructFoo promises it will work for any choice of a, as long as it's passed a value of type Foo a. But then the first equation returns a String, and the second equation returns an Int.
This is what you cannot do with a regular data type, and the new thing GADTs provide. In the first equation, the pattern match adds the constraint (a ~ String) to its context. In the second equation, the pattern match adds (a ~ Int).
If you haven't created a type where pattern-matching can cause type refinement, you don't have a GADT. You just have a type declared with GADT syntax. Which is fine - in a lot of ways, it's a better syntax than the basic data type syntax. It's just more verbose for the easiest cases.

Check if it is a specific type - haskell

I thought it would be really easy to find the answer online but I had no luck with that. Which means that my question should't be a question but I am sure more people new to Haskell might come up with the same question.
So how do I check if a value is of a certain type?
I have the following data type defined and I wanna check whether the input on a function is of a specific type.
data MyType a = MyInt Int | MyOther a (MyType a)
First, your data declaration will not work. Let's assume you're using this type:
data MyType a = MyInt Int | MyOther a (MyType a)
then you can have functions that take a MyType a, some specific MyType (e.g. MyType Int) or a constrained MyType (e.g. Num a => MyType a).
If you want to know whether you have a MyInt or a MyOther, you can simply use pattern matching:
whichAmI :: MyType a -> String
whichAmI (MyInt i) = "I'm an Int with value " ++ show i
whichAmI (MyOther _ _) = "I'm something else"
When you want to know if the type in the parameter a is a Num, or what type it is, you will run into a fundamental Haskell limitation. Haskell is statically typed so there is no such dynamic checking of what the a in MyType a is.
The solution is to limit your function if you need a certain type of a. For example we can have:
mySum :: Num a => MyType a -> a
mySum (MyInt i) = fromIntegral i
mySum (MyOther n m) = n + mySum m
or we can have a function that only works if a is a Bool:
trueOrGE10 :: MyType Bool -> Bool
trueOrGE10 (MyInt i) = i >= 10
trueOrGE10 (MyOther b _) = b
As with all Haskell code, it will need to be possible to determine at compile-time whether a particular expression you put into one of these functions has the right type.

Haskell custom datatype with parameter

I have a custom data type as follows:
data MyType a = Nothing
| One a
The idea is to have a function that return the data type. For example,
func (One Char) should return Char -- return the data type
I tried to implement func as follow:
func :: MyType a -> a
func (One a) = a
-- don't worry about Nothing for now
The code compiled but when I tried to run func (One Char) it gives me an error: Not in scope: data constructor ‘Char’
What is going on?
Try func (One "Hello") it will work.
The reason is that Haskell thinks you are trying to give it a data-constructor because you wrote a upper-case Char so just give it some real value ;)
BTW: In case you really want to give the type Char: that's in general not possible in Haskell as you need a dependent-type caps (see Idris for example).
That's not really how haskell works. Char is a type, so we can write
func :: MyType Char -> Char
meaning that we expect the "something" of MyType to be a Char.
Checking what type an argument has is probably valid in something like Java, but is not the way functional programming works.
I don't think there's much chance you really want this with your current level of understanding of Haskell (it's a stretch for me, and I've been at it a while), but if you really really do, you can actually get something pretty close.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PolyKinds #-} --might as well
-- I renamed Nothing to None to avoid conflicting with Maybe.
-- Since we're using DataKinds, this creates not only a type
-- constructor MyType and data constructors None and One,
-- but also a *kind* MyType and *type* constructors None and
-- One.
data MyType a = None | One a
-- We can't make a *function*, func, to take One Char and
-- produce Char, but we can make a *type function* (called
-- a type family) to do that (although I don't really know
-- why you'd want this particular one.
type family Func (a :: MyType k) :: k
type instance Func (One a) = a
Now if we write
Prelude> '3' :: Func (One Char)
GHCi is perfectly happy with it. In fact, we can make this type function even more general:
type family Func2 (a :: g) :: k where
Func2 (f a) = a
Now we can write
'c' :: Func2 (One Char)
but we can also write
'c' :: Func2 (Maybe Char)
and even
'c' :: Func2 (Either Char)
'c' :: Func2 ((Either Int) Char)
But in case you think anything goes,
'c' :: Func2 (Maybe Int)
or
'c' :: Func2 Char
will give errors.

Resources