Error when making an instance of Eq typeclass in Haskell - haskell

I am learning Haskell and writing a small decision diagrams library as a starting project. I have declared the data type as
data DD a = DDNode { var :: Int, vals :: [DD a]} | DDLeaf { val :: a} deriving (Show, Eq)
For testing for equality between 2 DDs, I am making an instance of Eq for DD. It basically does the same as testing for node and leaf equality in the case of tree structures.
instance (Eq a) => DD a where
(DDNode i vs) == (DDNode i' vs') = i == i' && vs == vs'
(DDLeaf v) == (DDLeaf v') = v == v'
_ == _ = False
When I load a file with the above code in GHCi, I get the following error,
Prelude> :load decisionDiagrams.hs
[1 of 1] Compiling DecisionDiagram ( decisionDiagrams.hs, interpreted )
decisionDiagrams.hs:9:19: error:
‘==’ is not a (visible) method of class ‘DD’
Failed, modules loaded: none.
What am I doing wrong?

You can not use Eq both in deriving and in an instance declaration, since then there are two implementations. The deriving (Eq) should thus be removed:
data DD a
= DDNode { var :: Int, vals :: [DD a]}
| DDLeaf { val :: a}
deriving (Show)
You need to specify that you are defining an instance of Eq, so the instance declaration should look like:
-- ↓ defining an instance for Eq
instance (Eq a) => Eq (DD a) where
-- …
The Eq instance you are implementing, is the one that Haskell can automatically derive. You thus do not need to construct such instance yourself: you can do this with a deriving clause. There is thus no reason to implement Eq manually.

Related

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) ] ]

I get an error when i try deriving eq. How can i fix this?

I am getting this error:
No instance for (Eq T1)
arising from the first field of TT' (typeMatrix T1')
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
When deriving the instance for (Eq TT)
|
20 | } deriving (Eq, Ord)
and I don't know why and how I can fix this ( error is the same for Ord)
Here's my code:
import Data.Matrix
data T1 = T1 { x :: Char
, y :: Int
, z :: Int
}
instance Show T1 where
show t1 = [(x t1)]
data TT = TT { myMap :: Matrix T1
, flag :: Int
} deriving (Eq, Ord)
Any idea?
In your example, a value of type TT contains a value of type T1; thus, to equate two values of type TT, you also need to know how to equate two values of type T1. But you haven't defined an Eq instance for T1! Add a deriving (Eq) clause to T1 and the error will go away. The same applies to Ord.
In general, if you have a type A, which contains a value of type B, in order to derive a typeclass on A, you need to derive that same typeclass on B. As described above, this occurs because in order to implement the methods of that typeclass on A, you need to already know how that typeclass behaves on B e.g. you can't equate A values unless you know how B values are equal (which is your example above). Another example: if you want to show values of type A as a String, you need to be able to convert B to a string.

Deriving extensions with multiparameter types

I have an Ast type constructor, parameterized by the identifier type.
Using the DeriveFunctor, DeriveFoldable and DeriveTraversable extensions
it is possible to automatically create the appropriate instances.
Now I find it useful to introduce more type parameters but unfortunately
the above method doesn't scale. Ideally I would like to be able to
wrap my Ast type in selection types which would allow me to fmap to
the appropriate type parameters. Is there some way to achieve a similar
effect without having to define the instances myself?
edit:
Here is a small example of what the original Ast looked like:
Ast id = Ast (FuncDef id)
deriving (Show, Functor, Foldable, Traversable)
FuncDef id = FuncDef id [Fparam id] (Block id)
deriving (Show, Functor, Foldable, Traversable)
Block id = Block [Stmt id]
deriving (Show, Functor, Foldable, Traversable)
..
After fiddling around all day I came to the following conclusions:
The Ast presented in the question turned out not to be very flexible.
In later stages I want to annotate different nodes in a way that can't
be expressed by just parameterizing the original Ast.
So I changed the Ast in order to act as a base for writing new types:
Ast funcdef = Ast funcdef
deriving (Show)
Header id fpartype = Header id (Maybe Type) [fpartype]
deriving (Show)
FuncDef header block = FuncDef header block
deriving (Show)
Block stmt = Block [stmt]
deriving (Show)
Stmt lvalue expr funccall =
StmtAssign lvalue expr |
StmtFuncCall funccall |
..
Expr expr intConst lvalue funccall =
ExprIntConst intConst |
ExprLvalue lvalue |
ExprFuncCall funccall |
expr :+ expr |
expr :- expr |
..
Now I can simply define a chain of newtypes for each compiler stage.
The Ast at the stage of the renamer may be parameterized around the identifier type:
newtype RAst id = RAst { ast :: Ast (RFuncDef id) }
newtype RHeader id = RHeader { header :: Header id (RFparType id) }
newtype RFuncDef id = RFuncDef {
funcDef :: FuncDef (RHeader id) (RBlock id)
}
..
newtype RExpr id = RExpr {
expr :: Expr (RExpr id) RIntConst (RLvalue id) (RFuncCall id)
}
During the typechecking stage the Ast may be parameterized by
the different internal types used in the nodes.
This parameterization allows for constructing Asts with Maybe wrapped
parameters in the middle of each stage.
If everything is ok we can use fmap to remove the Maybes and prepare the tree for the next stage. There are other ways Functor, Foldable and Traversable are useful so these are a must to have.
At this point I figured that what I want is most likely not possible
without metaprogramming so I searched for a template haskell solution.
Sure enough there is the genifunctors library which implements generic
fmap, foldMap and traverse functions. Using these it's a simple matter
of writing a few newtype wrappers to make different instances of the required typeclasses around the appropriate parameters:
fmapGAst = $(genFmap Ast)
foldMapGAst = $(genFoldMap Ast)
traverseGast = $(genTraverse Ast)
newtype OverT1 t2 t3 t1 = OverT1 {unwrapT1 :: Ast t1 t2 t3 }
newtype OverT2 t1 t3 t2 = OverT2 {unwrapT2 :: Ast t1 t2 t3 }
newtype OverT3 t1 t2 t3 = OverT3 {unwrapT3 :: Ast t1 t2 t3 }
instance Functor (OverT1 a b) where
fmap f w = OverT1 $ fmapGAst f id id $ unwrapT1 w
instance Functor (OverT2 a b) where
fmap f w = OverT2 $ fmapGAst id f id $ unwrapT2 w
instance Functor (OverT3 a b) where
fmap f w = OverT3 $ fmapGAst id id f $ unwrapT3 w
..

How to use polymorphic datatypes with fclabels?

TL;DR: I want to use fclabels with my polymorphic datatype, but obtaining wired errors with it.
data R a = A { cb :: a }
| B { cb :: a, cd :: a}
deriving (Show, Read, Eq)
So, my type is a sum off multiple variants with different number of fields. Some of the fields have the same names and it is important for me.
When I am converting it to underscored version and run mkLabel template:
data R a = A { _cb :: a }
| B { _cb :: a, _cd :: a }
deriving (Show, Read, Eq)
mkLabel ''R
I have some errors that I do not understand:
λ :load AminoAcidLens.hs
[1 of 1] Compiling AminoAcidLens ( AminoAcidLens.hs, interpreted )
AminoAcidLens.hs:13:1: error:
Multiple declarations of ‘cb’
Declared at: AminoAcidLens.hs:13:1
AminoAcidLens.hs:13:1
AminoAcidLens.hs:13:1: error:
Duplicate type signatures for ‘cb’
at AminoAcidLens.hs:13:1-11
AminoAcidLens.hs:13:1-11
AminoAcidLens.hs:13:1: error:
Duplicate INLINE pragmas for ‘cb’
at AminoAcidLens.hs:13:1-11
AminoAcidLens.hs:13:1-11
Failed, modules loaded: none.
If I change _cds type to any other, the errors disappear:
data R a = A { _cb :: a }
| B { _cb :: a, _cd :: Int }
deriving (Show, Read, Eq)
mkLabel ''R
So, why do I have these errors and how to fix them?

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)

Resources