Derived instance in Haskell - haskell

I would like to use derived instance like this:
data Test3D = forall a. (Show a, Eq a, Typeable a, Generic a)
=> Test3D { testDt :: String
, testPrm :: a
}
deriving (Show, Eq, Typeable, Generic)
instance Binary (Test3D)
$(deriveJSON defaultOptions ''Test3D)
But I received from GHC:
• Can't make a derived instance of ‘Show Test3D’:
Constructor ‘Test3D’ has existentials or constraints in its type
Possible fix: use a standalone deriving declaration instead
• In the data declaration for ‘Test3D’
This way is very convenient for my project. I can not find the solution.
Is any way of using derived instance for such data?

Is any way of using derived instance for such data?
Yes. Do what GHC suggested, make a standalone deriving clause:
{-# LANGUAGE StandaloneDeriving, ExistentialQuantification #-}
data Test3D = forall a. (Show a)
=> Test3D { testDt :: String
, testPrm :: a
}
deriving instance Show Test3D
What you cannot do is derive an Eq instance, because different values may actually contain different types and it's only possible to compare these with a dynamic-cast hack through Typeable.

Related

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.

Is it possible to declare a constrained data type using record syntax?

Is it possible to declare a constrained data type using record syntax? My attempt
data ConstrainedRecord a where
ConstrainedRecord :: Num a => { first :: a, second :: a }
causes GHC to complain "Record syntax is illegal here".
Yes, but in GADT syntax you always have to explicitly specify the return type of the constructor:
data ConstrainedRecord a where
ConstrainedRecord :: Num a => { first :: a, second :: a } -> ConstrainedRecord a
(Also, this may come handy:
deriving instance (Show a) => Show (ConstrainedRecord a)
using StandaloneDeriving, since a normal deriving does not work.)

Haskell: How to make a type an instance of two typeclasses?

Is it possible to make Level an instance of Eq and Ord?
instance Eq Ord Level where
compare First Second = LT
...
I've tried this
instance (Ord, Eq) => Level where ...
But I've got an error
‘compare’ is not a (visible) method of class ‘Level’
I know I can use deriving (Eq) on my data Level. But I cannot change my data.
Use two instances
instance Eq Level where
x == y = ...
instance Ord Level where
compare x y = ...
Alternatively, use the standalone deriving extension:
{-# LANGUAGE StandaloneDeriving #-}
... -- ^^^^^^^^^^^^^^^^^^ must be at the top of the file
deriving instance (Eq Level)
deriving instance (Ord Level)

Automatically deriving PathPiece

In my Yesod web-application I have following data type:
data SensorType = TemperatureSensor | HumiditySensor deriving (Eq, Show, Read, PathPiece, PersistField)
I enable GeneralizedNewtypeDeriving
The answer about automatically deriving PathPiece:
What typeclasses need to be defined for a Yesod path?
But I get ghc-error:
Can't make a derived instance of `PathPiece SensorType
`PathPiece' is not a derivable class
Is it possible automatically derive PathPiece? What I do wrong?
For PersistField exists derivePersistField. What about PathPiece?
GeneralizedNewtypeDeriving, as its name implies, is only useful for deriving instances for newtypes. It works by lifting instances of the underlying type over the newtype wrapper.
Your type is not a newtype so there is no PathPiece instance to lift.
It doesn't look like that's possible, based on the path-pieces package not doing anything like that or any code I can find on Github. I would implement the PathPiece typeclass like this (using tshow and readMay from classy prelude):
instance PathPiece SensorType where
toPathPiece = tshow
fromPathPiece = readMay

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.

Resources