Matching on a particular type of a parametric type - haskell

I'm trying to work with an external library that has provided a parametric type like this:
data ParametricType a = TypeConstructor a
I have a typeclass, something like this:
class GetsString a where
getString :: a -> String
and I'd like to execute some code if ParametricType's a is a specific type. I've tried narrowing the type when instantiating the typeclass:
data HoldsString = HoldsString String
instance GetsString (ParametricType HoldsString) where
getString (TypeConstructor (HoldsString str)) = str
which errors with Illegal instance declaration for‘GetsString (ParametricType HoldsString)’(All instance types must be of the form (T a1 ... an)
and I've tried pattern matching on the type:
instance GetsString (ParametricType a) where
getString (TypeConstructor (HoldsString str)) = str
for which I receive Couldn't match expected type ‘a’ with actual type ‘HoldsString’‘a’ is a rigid type variable bound by the instance declaration.
Is there a way to do this, or am I conceptually on the wrong track here?

You're just missing the FlexibleInstances extension. Put {-# LANGUAGE FlexibleInstances #-} at the top of your file, or do :set -XFlexibleInstances if you're typing into GHCi directly, and then your first attempt will work.

Related

Using a default implementation of typeclass method to omit an argument

I want to be able to define a (mulit-parameter-) typeclass instance whose implementation of the class's method ignores one of its arguments. This can be easily done as follows.
instance MyType MyData () where
specific _ a = f a
As I'm using this pattern in several places, I tried to generalize it by adding a specialized class method and adequate default implementations. I came up with the following.
{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
class MyType a b where
specific :: b -> a -> a
specific = const dontCare
dontCare :: a -> a
dontCare = specific (undefined :: b)
{-# MINIMAL specific | dontCare #-}
This however yields the error Could not deduce (MyType a b0) arising from a use of ‘dontCare’ [..] The type variable ‘b0’ is ambiguous. I don't see why the latter should be the case with the type variable b being scoped from the class signature to the method declaration. Can you help me understand the exact problem that arises here?
Is there another reasonable way to achieve what I intended, namely to allow such trimmed instances in a generic way?
The problem is in the default definition of specific. Let's zoom out for a second and see what types your methods are actually given, based on your type signatures.
specific :: forall a b. MyType a b => b -> a -> a
dontCare :: forall a b. MyType a b => a -> a
In the default definition of specific, you use dontCare at type a -> a. So GHC infers that the first type argument to dontCare is a. But nothing constrains its second type argument, so GHC has no way to select the correct instance dictionary to use for it. This is why you ended up needing AllowAmbiguousTypes to get GHC to accept your type signature for dontCare. The reason these "ambiguous" types are useful in modern GHC is that we have TypeApplications to allow us to fix them. This definition works just fine:
class MyType a b where
specific :: b -> a -> a
specific = const (dontCare #_ #b)
dontCare :: a -> a
dontCare = specific (undefined :: b)
{-# MINIMAL specific | dontCare #-}
The type application specifies that the second argument is b. You could fill in a for the first argument, but GHC can actually figure that one out just fine.

Pattern bindings for existential constructors

While writing Haskell as a programmer that had exposure to Lisp before, something odd came to my attention, which I failed to understand.
This compiles fine:
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ExistentialQuantification #-}
data Foo = forall a. Show a => Foo { getFoo :: a }
showfoo :: Foo -> String
showfoo Foo{getFoo} = do
show getFoo
whereas this fails:
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ExistentialQuantification #-}
data Foo = forall a. Show a => Foo { getFoo :: a }
showfoo :: Foo -> String
showfoo foo = do
let Foo{getFoo} = foo
show getFoo
To me it's not obvious why the second snippet fails.
The question would be:
Do I miss something or stems this behaviour from the fact that haskell is not homoiconic?
My reasoning is, given that:
Haskell needs to implement record pattern matching as a compiler extension, because of it's choice to use syntax rather than data.
Matching in a function head or in a let clause are two special cases.
It is difficult to understand those special cases, as they cannot be either implemented nor looked up directly in the language itself.
As an effect of this, consistent behaviour throughout the language is not guaranteed. Especially together with additional compiler extensions, as per example.
ps: compiler error:
error:
• My brain just exploded
I can't handle pattern bindings for existential or GADT data constructors.
Instead, use a case-expression, or do-notation, to unpack the constructor.
• In the pattern: Foo {getFoo}
In a pattern binding: Foo {getFoo} = foo
In the expression:
do { let Foo {getFoo} = foo;
show getFoo }
edit:
A different compiler version gives this error for the same problem
* Couldn't match expected type `p' with actual type `a'
because type variable `a' would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor: Foo :: forall a. Show a => a -> Foo
Do I miss something or stems this behaviour from the fact that haskell is not homoiconic?
No. Homoiconicity is a red herring: every language is homoiconic with its source text and its AST1, and indeed, Haskell is implemented internally as a series of desugaring passes between various intermediate languages.
The real problem is that let...in and case...of just have fundamentally different semantics, which is intentional. Pattern-matching with case...of is strict, in the sense that it forces the evaluation of the scrutinee in order to choose which RHS to evaluate, but pattern bindings in a let...in form are lazy. In that sense, let p = e1 in e2 is actually most similar to case e1 of ~p -> e2 (note the lazy pattern match using ~!), which produces a similar, albeit distinct, error message:
ghci> case undefined of { ~Foo{getFoo} -> show getFoo }
<interactive>:5:22: error:
• An existential or GADT data constructor cannot be used
inside a lazy (~) pattern
• In the pattern: Foo {getFoo}
In the pattern: ~Foo {getFoo}
In a case alternative: ~Foo {getFoo} -> show getFoo
This is explained in more detail in the answer to Odd ghc error message, "My brain just exploded"?.
1If this doesn’t satisfy you, note that Haskell is homoiconic in the sense that most Lispers use the word, since it supports an analog to Lisp’s quote operator in the form of [| ... |] quotation brackets, which are part of Template Haskell.
I thought about this a bit and albeit the behaviour seems odd at first, after some thinking I guess one can justify it perhaps thus:
Say I take your second (failing) example and after some massaging and value replacements I reduce it to this:
data Foo = forall a. Show a => Foo { getFoo :: a }
main::IO()
main = do
let Foo x = Foo (5::Int)
putStrLn $ show x
which produces the error:
Couldn't match expected type ‘p’ with actual type ‘a’ because type variable ‘a’ would escape its scope
if the pattern matching would be allowed, what would be the type of x? well.. the type would be of course Int. However the definition of Foo says that the type of the getFoo field is any type that is an instance of Show. An Int is an instance of Show, but it is not any type.. it is a specific one.. in this regard, the actual specific type of the value wrapped in that Foo would become "visible" (i.e. escape) and thus violate our explicit guarantee that forall a . Show a =>...
If we now look at a version of the code that works by using a pattern match in the function declaration:
data Foo = forall a . Show a => Foo { getFoo :: !a }
unfoo :: Foo -> String
unfoo Foo{..} = show getFoo
main :: IO ()
main = do
putStrLn . unfoo $ Foo (5::Int)
Looking at the unfoo function we see that there is nothing there saying that the type inside of the Foo is any specific type.. (an Int or otherwise) .. in the scope of that function all we have is the original guarantee that getFoo can be of any type which is an instance of Show. The actual type of the wrapped value remains hidden and unknowable so there are no violations of any type guarantees and happiness ensues.
PS: I forgot to mention that the Int bit was of course an example.. in your case, the type of the getFoo field inside of the foo value is of type a but this is a specific (non existential) type to which GHC's type inference is referring to (and not the existential a in the type declaration).. I just came up with an example with a specific Int type so that it would be easier and more intuitive to understand.

Type Family Equivalent of `Eq`?

Type Families with Class shows:
As I incompletely understand, this slide shows 2 ways of implementing Eq: via a type class or type family.
I'm familiar with type classes and thus implemented MyEq:
class MyEq a where
eq :: a -> a -> Bool
But, when I tried to define the type family version, it failed to compile:
data Defined = Yes | No
type family IsEq (a :: *) :: Defined
due to:
TypeEq.hs:30:30: error:
• Type constructor ‘Defined’ cannot be used here
(Perhaps you intended to use DataKinds)
• In the kind ‘Defined’
Please explain how to implement the type family version of the Eq type class.
Also, it'd be helpful, please, to show an implementation of such a type family instance (if that's even the right word).
This is kind of neat, glad to have stumbled across this. For the interested, here is the slide deck and here is the paper. This is a usual case of needing some language extensions.
{-# LANGUAGE DataKinds, TypeFamilies, TypeOperators, ConstraintKinds #-}
data Defined = Yes | No
type family IsEq (a :: *) :: Defined
type Eq a = IsEq a ~ Yes
Then, the "implementation" of this are instances like
type instance IsEq () = Yes -- '()' is an instance of 'Eq'
type instance IsEq Int = Yes -- 'Int' is an instance of 'Eq'
type instance IsEq [a] = IsEq a -- '[a]' is an instance of 'Eq' is 'a' is
You can "try" them out at GHCi:
ghci> :kind! IsEq [Int]
IsEq [Int] :: Defined
= Yes
But the paper and slide deck doesn't really worry too much about actually providing an equality function. (It mentions storing it in a field of Yes). So, why is this interesting if it isn't even ready to provide class methods? Because
it makes for a better mechanism than overlapping classes
backtracking search is easier than with typeclasses
it makes it possible to fail early with nice error message (encoded as a field in the No constructor)
Try adding DataKinds As a language extension (i.e. to the top of the file under a "language" pragma) as the error message suggests.
I haven't watched the talk, but iiuc, Defined is just Bool, where Yes is True. So if you enable DataKinds, you can just use IsEq a ~ 'True (and the apostrophe before True just means "this is a type").
Some background: what this extension does is "raise" every value of any algebraic datatypes (i.e. Declared with data, but not GADTs, iiuc) into its own type; and then raises each type into its own kind (a "kind" in Haskell is the "type of types"), i.e. not of "kind *" (pronounced "kind star"), which is the kind of normal Haskell values that exist at runtime.
btw:
[Bool] :: * means that "a list of liens is a type". and [] :: * -> * means that the type constructor for lists has kind "type to type", i.e. "once you give List a single type, you get back a type".

Extension OverloadedString doesn't fully infer IsString. Why? Or what am I missing?

ghc 7.6.3
is quite upset for some code i'm trying to compile
the error is
No instance for (Data.String.IsString t3)
arising from the literal `"meh"'
The type variable `t3' is ambiguous
i don't understand. it's a literal. what is ambiguous? why can't it infer this as a string?
this is coming in a call like
foo bar "meh"
where foo doesn't require the second argument to be anything in particular (it must satisfy some typeclass, and it does for the particular combos it is getting.)
i'll note i can fix this error by changing the call to
foo bar ("meh" :: String)
which is clearly insane.
-- edit
maybe it has nothing to do with overloadedStrings
i can "reproduce" this error just with
data B a where
Foo :: a -> B A
then in GHCi writing simply
Foo "ok"
(clearly this fails as i'm not deriving Show, but why do i also get
No instance for (Data.String.IsString a0)
arising from the literal `"ok"'
The type variable `a0' is ambiguous
...
? what's going on here? what does this mean?)
it's a literal. what is ambiguous? why can't it infer this as a string?
When you use OverloadedStrings "meh" is not a literal String. It's a literal polymorphic value of type IsString a => a. Its type can't be inferred as String because it could also be used as a lazy ByteString, strict ByteString, Text, etc..
foo doesn't require the second argument to be anything in particular
If foo doesn't require the second argument to be anything in particular how does the type checker know the argument to foo should be a String, rather than a Text, etc.?
i'll note i can fix this error by changing the call to foo bar ("meh" :: String) which is clearly insane.
Now you are telling the type checker which specific type you want for "meh".
maybe it has nothing to do with overloadedStrings
It is exactly to do with OverloadedStrings. Personally I recommend not using OverloadedStrings and just using Data.String.fromString precisely because of the confusing behaviour you are seeing.
i can "reproduce" this error just with ... what's going on here? what does this mean?
Here's a concrete example of the ambiguity.
{-# LANGUAGE OverloadedStrings, FlexibleInstances #-}
import Data.Text
class Foo a where
foo :: a -> String
instance Foo String where
foo _ = "String"
instance Foo Text where
foo _ = "Text"
main :: IO ()
main = print (foo "meh")
What should main print? It depends on the type of "meh". What type did the user want for "meh"? With OverloadedStrings on, there's no way to know.

List of existentially quantified values in Haskell

I'm wondering why this piece of code doesn't type-check:
{-# LANGUAGE ScopedTypeVariables, Rank2Types, RankNTypes #-}
{-# OPTIONS -fglasgow-exts #-}
module Main where
foo :: [forall a. a]
foo = [1]
ghc complains:
Could not deduce (Num a) from the context ()
arising from the literal `1' at exist5.hs:7:7
Given that:
Prelude> :t 1
1 :: (Num t) => t
Prelude>
it seems that the (Num t) context can't match the () context of arg. The point I can't understand is that since () is more general than (Num t), the latter should and inclusion of the former. Has this anything to do with lack of Haskell support for sub-typing?
Thank you for any comment on this.
You're not using existential quantification here. You're using rank N types.
Here [forall a. a] means that every element must have every possible type (not any, every). So [undefined, undefined] would be a valid list of that type and that's basically it.
To expand on that a bit: if a list has type [forall a. a] that means that all the elements have type forall a. a. That means that any function that takes any kind of argument, can take an element of that list as argument. This is no longer true if you put in an element which has a more specific type than forall a. a, so you can't.
To get a list which can contain any type, you need to define your own list type with existential quantification. Like so:
data MyList = Nil | forall a. Cons a MyList
foo :: MyList
foo = Cons 1 Nil
Of course unless you restrain element types to at least instantiate Show, you can't do anything with a list of that type.
First, your example doesn't even get that far with me for the current GHC, because you need to enable ImpredecativeTypes as well. Doing so results in a warning that ImpredicativeTypes will be simplified or removed in the next GHC. So we're not in good territory here. Nonetheless, adding the proper Num constraint (foo :: [forall a. Num a => a]) does allow your example to compile.
Let's leave aside impredicative types and look at a simpler example:
data Foo = Foo (forall a. a)
foo = Foo 1
This also doesn't compile with the error Could not deduce (Num a) from the context ().
Why? Well, the type promises that you're going to give the Foo constructor something with the quality that for any type a, it produces an a. The only thing that satisfies this is bottom. An integer literal, on the other hand, promises that for any type a that is of class Num it produces an a. So the types are clearly incompatible. We can however pull the forall a bit further out, to get what you probably want:
data Foo = forall a. Foo a
foo = Foo 1
So that compiles. But what can we do with it? Well, let's try to define an extractor function:
unFoo (Foo x) = x
Oops! Quantified type variable 'a' escapes. So we can define that, but we can't do much interesting with it. If we gave a class context, then we could at least use some of the class functions on it.
There is a time and place for existentials, including ones without class context, but its fairly rare, especially when you're getting started. When you do end up using them, often it will be in the context of GADTs, which are a superset of existential types, but in which the way that existentials arise feels quite natural.
Because the declaration [forall a. a] is (in meaning) the equivalent of saying, "I have a list, and if you (i.e. the computer) pick a type, I guarantee that the elements of said list will be that type."
The compiler is "calling your bluff", so-to-speak, by complaining, "I 'know' that if you give me a 1, that its type is in the Num class, but you said that I could pick any type I wanted to for that list."
Basically, you're trying to use the value of a universal type as if it were the type of a universal value. Those aren't the same thing, though.

Resources