Stackoverflow exception when comparing two dynamic types - haskell

I have defined a data type Loc which can accept Dynamics in the constructor. Moreover I need to compare Loc datatypes using == operator. So I came up with something like this:
data Loc = UnknownLoc | DynamicLoc Dynamic deriving (Eq,Show)
instance Eq Dynamic
data DynamicLocation = Loc_1 | Loc_2 deriving (Eq,Show)
instance Typeable DynamicLocation
But when attempting to run the following line I get stackoverflow exception.
DynamicLoc (toDyn Loc_1) == DynamicLoc (toDyn Loc_1)
any idea?

Please, read your compiler warnings :) You haven't provided a definition for the Typeable typeclass's typeOf method for DynamicLocation, and toDyn calls typeOf. So this definitely shouldn't work -- if you try just toDyn Loc_1, you'll get an exception.
But why an infinite loop? It's because you also haven't defined (==) for Dynamic, and (==) and (/=) are defined in terms of each other in GHC.Classes. GHC doesn't attempt to resolve such infinite recursion in default method declarations, so you unfortunately don't get a warning.
What to do? I suggest letting GHC derive the Typeable instance for you:
{-# LANGUAGE StandaloneDeriving, DeriveDataTypeable #-}
data DynamicLocation = Loc_1 | Loc_2 deriving (Eq,Show)
deriving instance Typeable DynamicLocation
or, more sensible:
{-# LANGUAGE DeriveDataTypeable #-}
data DynamicLocation = Loc_1 | Loc_2 deriving (Eq,Show,Typeable)
However, as a commenter has already pointed out, it's not immediately clear how to define (==) for Dynamic, or if this is even possible.

Related

Is there a way to shorten this deriving clause?

Is there a way to write the following:
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveAnyClass #-}
data X = A | B | C
deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SMTValue)
So that the deriving clause can be shortened somehow, to something like the following:
data X = A | B | C deriving MyOwnClass
I'd like to avoid TH if at all possible, and I'm happy to create a new class that has all those derived classes as its super-class as necessary (as in MyOwnClass above), but that doesn't really work with the deriving mechanism. With constraint kinds extension, I found that you can write this:
type MyOwnClass a = (Eq a, Ord a, Show a, Read a, Data a, SymWord a, HasKind a, SMTValue a)
Unfortunately, I cannot put that in the deriving clause. Is there some magic to make this happen?
EDIT From the comments, it appears TH might be the only viable choice here. (The CPP macro is really not OK!) If that's the case, the sketch of a TH solution will be nice to see.
There's bad and easy way to do it and good but hard way. As Silvio Mayolo said you can use TemplateHaskell to write such function. This way is hard and rather complex way. The easier way is to use C-preprocessor like this:
{-# LANGUAGE CPP #-}
#define MY_OWN_CLASS (Eq, Ord, Show, Read, Data, SymWord, HasKind, SMTValue)
data X = A | B | C
deriving MY_OWN_CLASS
UPDATE (17.07.2016): ideas & sketch of TH solution
Before introducing sketch of solution I will illustrate why this is harder to do with TH. deriving-clause is not some independent clause, it's a part of data declaration so you can't encode only part inside deriving unfortunately. The general approach of writing any TH code is to use runQ command on brackets to see what you should write in the end. Like this:
ghci> :set -XTemplateHaskell
ghci> :set -XQuasiQuotes
ghci> import Language.Haskell.TH
ghci> runQ [d|data A = B deriving (Eq, Show)|]
[ DataD
[]
A_0
[]
Nothing
[ NormalC B_1 [] ]
[ ConT GHC.Classes.Eq , ConT GHC.Show.Show ]
]
Now you see that type classes for deriving are specified as last argument of DataD — data declaration — constructor. The workaround for your problem is to use -XStadandaloneDeriving extension. It's like deriving but much powerful though also much verbose. Again, to see, what exactly you want to generate, just use runQ:
ghci> data D = T
ghci> :set -XStandaloneDeriving
ghci> runQ [d| deriving instance Show D |]
[ StandaloneDerivD [] (AppT (ConT GHC.Show.Show) (ConT Ghci5.D)) ]
You can use StandaloneDerivD and other constructors directly or just use [d|...|]-brackets though they have more magic but they give you list of Dec (declarations). If you want to generate several declarations then you should write you function like this:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE StandaloneDeriving #-}
module Deriving where
import Language.Haskell.TH
boilerplateAnnigilator :: Name -> Q [Dec]
boilerplateAnnigilator typeName = do
let typeCon = conT typeName
[d|deriving instance Show $(typeCon)
deriving instance Eq $(typeCon)
deriving instance Ord $(typeCon)
|]
Brief tutorial can be found here.
And then you can use it in another file (this is TH limitation called staged restriction: you should define macro in one file but you can't use it in the same file) like this:
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
import Deriving
data X = A | B | C
boilerplateAnnigilator ''X
You should put other type classes you want inside boilerplateAnnigilator function. But this approach only works for non-parametrized class. If you have data MyData a = ... then standalone deriving should look like:
deriving instance Eq a => MyData a
And if you want your TH macro work for parametrized classes as well, then you basically should implement whole logic of GHC compiler by deducing whether type have type variables or not and generate instances depending on that. But this is much harder. I think that the best solution is to just make ticket in GHC compiler and let authors implement such feature called deriving aliases :)

What is the difference between `DeriveAnyClass` and an empty instance?

Using the cassava package, the following compiles:
{-# LANGUAGE DeriveGeneric #-}
import Data.Csv
import GHC.Generics
data Foo = Foo { foo :: Int } deriving (Generic)
instance ToNamedRecord Foo
However, the following does not:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
import Data.Csv
import GHC.Generics
data Foo = Foo { foo :: Int } deriving (Generic, ToNamedRecord)
The compiler reports:
test.hs:7:50:
No instance for (ToNamedRecord Int)
arising from the first field of ‘Foo’ (type ‘Int’)
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
When deriving the instance for (ToNamedRecord Foo)
This leaves me with two questions: Why isn't the second version identical to the first? And why is the compiler hoping to find an instance for ToNamedRecord Int?
NB: As pointed out by David in the comments, GHC has been updated since I wrote this. The code as written in the question compiles and works correctly. So just imagine everything below is written in the past tense.
The GHC docs say:
The instance context will be generated according to the same rules
used when deriving Eq (if the kind of the type is *), or the rules for
Functor (if the kind of the type is (* -> *)). For example
instance C a => C (a,b) where ...
data T a b = MkT a (a,b) deriving( C )
The deriving clause will
generate
instance C a => C (T a b) where {}
The constraints C a and C (a,b) are generated from the data constructor arguments, but the
latter simplifies to C a.
So, according to the Eq rules, your deriving clause generates...
instance ToNamedRecord Int => ToNamedRecord Foo where
... which is not the same as...
instance ToNamedRecord Foo where
... in that the former is only valid if there's an instance ToNamedRecord Int in scope (which is appears there isn't in your case).
But I find the spec to be somewhat ambiguous. Should the example really generate that code, or should it generate instance (C a, C (a, b)) => instance C (T a b) and let the solver discharge the second constraint? It appears, in your example, that it's generating such constraints even for fields with fully-concrete types.
I hesitate to call this a bug, because it's how Eq works, but given that DeriveAnyClass is intended to make it quicker to write empty instances it does seem unintuitive.

Creating custom data types with constraints

I'm trying to create a custom data type. As an example
data Time = Second Int deriving (Show)
However, this is too limiting (we could say later need milliseconds). I would like to instead define something like this:
data Time = Second Num deriving (Show)
This doesn't compile because Num has kind * -> ghc-prim-0.4.0.0:GHC.Prim.Constraint
How do I setup Time such that Second may contain any Num?
One of the best examples of why this might not be so desirable is found here at the Wikibooks section on Classes and Types. They say:
Type constraints in data declarations are less useful than it might seem at first. Consider:
data (Num a) => Foo a = F1 a | F2 a String
Here, Foo is a type with two constructors, both taking an argument of a type a which must be in Num. However, the (Num a) => constraint is only effective for the F1 and F2 constructors, and not for other functions involving Foo. Therefore, in the following example...
fooSquared :: (Num a) => Foo a -> Foo a
fooSquared (F1 x) = F1 (x * x)
fooSquared (F2 x s) = F2 (x * x) s
... even though the constructors ensure a will be some type in Num we can't avoid duplicating the constraint in the signature of fooSquared
This suggests that a reasonable option for you is to just create Time with a generic parameter, and then later ensure that the module functions that operate on Time data always have the necessary constraint for Num.
It won't be so much of a worry that someone goes off and foolishly makes Time String or something -- if they do, then none of the provided module functions are going to be helpful for them, so it doesn't matter so much.
There are also options to look up with GADTs, the {-# LANGUAGE GeneralizedNewtypeDeriving #-} pragma, and the {-# LANGUAGE DatatypeContexts #-} pragma. But usually these start to rope in unnecessary degrees of extra complexity, especially if you're a Haskell novice like me.
There is a deprecated feature called Datatype Contexts that allows you to do that:
{-# LANGUAGE DatatypeContexts #-}
data Num a => Time a = Second a deriving (Show)
t = Second (5 :: Int)
main = print t
This executes on GHC 7.8.3 (sorry, don't have 7.10 to check), but warns you about the deprecation:
t.hs:1:14: Warning:
-XDatatypeContexts is deprecated: It was widely considered a
misfeature, and has been removed from the Haskell language.
Second 5
A non-deprecated way to do it is to use Generalized Algebraic Datatypes (GADTs) (and you'll need standalone deriving as well):
{-# LANGUAGE GADTs, StandaloneDeriving #-}
data Time a where
Second :: Num a => a -> Time a
deriving instance Show a => Show (Time a)
t = Second (5 :: Int)
main = print t
If you try to create a variable with something non-Num, you'll get a compilation error:
t = Second "a"
t.hs:12:5:
No instance for (Num [Char]) arising from a use of ‘Second’
In the expression: Second "a"
In an equation for ‘t’: t = Second "a"

deriving clause with arbitrary "Constraint aliases"?

For example, this declaration with deriving:
{-# LANGUAGE DeriveDataTypeable, ConstraintKinds #-}
import Data.Data (Data)
import Data.Typeable (Typeable)
type Constraints a = (Show a, Eq a, Ord a, Data a, Typeable a)
data A = A deriving (Constraints)
errors with:
Illegal deriving item ‘Constraints’
Which makes sense given http://downloads.haskell.org/~ghc/7.8.3/docs/html/users_guide/deriving.html
I write deriving (Show, Eq, Ord, Data, Typeable) for most of my types. It might be nice to export standard "constraint aliases", i.e. any type of kind * -> Constraint. Given, of course, that the constraints in the constraint tuple are all the right arity, have an empty "minimal complete definition", etc.
Is there any proposal for this? How hard would it be? Are there alternatives?
There is no proposal for this. It wouldn't be too hard, but I suspect it wouldn't get a lot of traction. Not only could you use template haskell to generate standalone deriving declarations as a comment suggests, but you could macro-expand to your desired clause using CPP if you really want.

Is it possible to get the Kind of a Type Constructor in Haskell?

I am working with Data.Typeable and in particular I want to be able to generate correct types of a particular kind (say *). The problem that I'm running into is that TypeRep allows us to do the following (working with the version in GHC 7.8):
let maybeType = typeRep (Proxy :: Proxy Maybe)
let maybeCon = fst (splitTyConApp maybeType)
let badType = mkTyConApp maybeCon [maybeType]
Here badType is in a sense the representation of the type Maybe Maybe, which is not a valid type of any Kind:
> :k Maybe (Maybe)
<interactive>:1:8:
Expecting one more argument to ‘Maybe’
The first argument of ‘Maybe’ should have kind ‘*’,
but ‘Maybe’ has kind ‘* -> *’
In a type in a GHCi command: Maybe (Maybe)
I'm not looking for enforcing this at type level, but I would like to be able to write a program that is smart enough to avoid constructing such types at runtime. I can do this with data-level terms with TypeRep. Ideally, I would have something like
data KindRep = Star | KFun KindRep KindRep
and have a function kindOf with kindOf Int = Star (probably really kindOf (Proxy :: Proxy Int) = Star) and kindOf Maybe = KFun Star Star, so that I could "kind-check" my TypeRep value.
I think I can do this manually with a polykinded typeclass like Typeable, but I'd prefer to not have to write my own instances for everything. I'd also prefer to not revert to GHC 7.6 and use the fact that there are separate type classes for Typeable types of different kinds. I am open to methods that get this information from GHC.
We can get the kind of a type, but we need to throw a whole host of language extensions at GHC to do so, including the (in this case) exceeding questionable UndecidableInstances and AllowAmbiguousTypes.
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
import Data.Proxy
Using your definition for a KindRep
data KindRep = Star | KFun KindRep KindRep
we define the class of Kindable things whose kind can be determined
class Kindable x where
kindOf :: p x -> KindRep
The first instance for this is easy, everything of kind * is Kindable:
instance Kindable (a :: *) where
kindOf _ = Star
Getting the kind of higher-kinded types is hard. We will try to say that if we can find the kind of its argument and the kind of the result of applying it to an argument, we can figure out its kind. Unfortunately, since it doesn't have an argument, we don't know what type its argument will be; this is why we need AllowAmbiguousTypes.
instance (Kindable a, Kindable (f a)) => Kindable f where
kindOf _ = KFun (kindOf (Proxy :: Proxy a)) (kindOf (Proxy :: Proxy (f a)))
Combined, these definitions allow us to write things like
kindOf (Proxy :: Proxy Int) = Star
kindOf (Proxy :: Proxy Maybe) = KFun Star Star
kindOf (Proxy :: Proxy (,)) = KFun Star (KFun Star Star)
kindOf (Proxy :: Proxy StateT) = KFun Star (KFun (KFun Star Star) (KFun Star Star))
Just don't try to determine the kind of a polykinded type like Proxy
kindOf (Proxy :: Proxy Proxy)
which fortunately results in a compiler error in only a finite amount of time.

Resources