haskellderivingcoercederivingvia# Using Deriving Via with Phantom Types

Apologies for the long repro but I haven't been able to make it any shorter. The following code compiles fine until the last line:

```
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}
{-# LANGUAGE DerivingVia, DerivingStrategies, StandaloneDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Repro where
import Prelude hiding ((+))
class (Additive a) where
(+) :: a -> a -> a
data Vector2D u = Vector2D {
x :: u,
y :: u
}
addVector2 :: (Additive a) => Vector2D a -> Vector2D a -> Vector2D a
addVector2 Vector2D { x = x1, y = y1 } (Vector2D { x = x2, y = y2 }) =
Vector2D { x = x1 + x2, y = y1 + y2 }
instance (Additive a) => Additive (Vector2D a) where
(+) = addVector2
newtype Phantom1 d a = Phantom1 (Vector2D a) --Axial
deriving via (Vector2D a) instance forall d . (Additive a) => (Additive (Phantom1 d a))
data Via a b = Via a
class IsoEvidence a b where
convertTo :: a -> b
convertFrom :: b -> a
instance forall a b . (IsoEvidence a b, Additive b) => (Additive (Via a b)) where
(Via x) + (Via y) = Via $ convertFrom $ (convertTo x :: b) + (convertTo y :: b)
newtype Phantom2 d a = Phantom2 (Vector2D a) --Offset
instance (IsoEvidence (Phantom1 d a) (Phantom2 d a)) where
convertTo (Phantom1 x) = Phantom2 x
convertFrom (Phantom2 x) = Phantom1 x
deriving via (Via (Phantom2 d a) (Phantom1 d a))
instance (Additive a, IsoEvidence (Phantom1 d a) (Phantom2 d a)) =>
(Additive (Phantom2 d a))
```

After that I get the following error:

- Couldn't match representation of type
`Vector2D a`

with that of`Via (Phantom2 d a) (Phantom1 d a)`

Which seems to be saying it can't coerce "Via &c" to "Vector2D a", which is odd because it's literally a newtype two levels deep and that works fine.

What am I doing wrong here?

Solution

`DerivingVia`

works through newtypes, but you wrote

```
data Via a b = Via a -- should be newtype
```

- Comparing lists in Haskell
- Is there a non-identity monad morphism M ~> M that is monadically natural in M?
- Problem with loading module ‘Distribution.Simple’
- Improving efficiency in Stirling numbers calculation
- Does sequencing an infinite list of IO actions by definition result in a never-ending action? Or is there a way to bail out?
- How to call pgQuery from postgresql-query?
- How to avoid whitespace after a tag (link) in Hamlet templates?
- Understanding type-directed resolution in Haskell with existential types
- Why is seq bad?
- Understanding bind function in Haskell
- How to create route that will trigger on any path in Servant?
- How do I use a global state in WAI middleware?
- nixos 23.11 cabal install mysql-simple problem - "Missing (or bad) C libraries"
- Is there a way to kill all forked threads in a GHCi session without restarting it?
- Why can an invalid list expression such as 2:1 be assigned to a variable, but not printed?
- Iterate over a type level list and call a function based on each type in the list
- How does this solution of Project Euler Problem 27 in the Haskell Wiki work?
- Why `Monad` is required to use `pure`?
- Can't do partial function definitions in GHCi
- recommended way to convert Double -> Float in Haskell
- Haskell profiling understanding cost centre summary for anonymous lambda
- Why is Haskell fully declarative?
- GHC Generating Redundant Core Operations
- Question about Event firing in reflex-frp
- Using Haskell's "Maybe", type declarations
- How can I elegantly invert a Map's keys and values?
- Why there is no output for wrapped IO in Haskell?
- What are the definitions of Weather and Memory in xmobar repo?
- Serializing a Data.Text value to a ByteString without unnecessary \NUL bytes
- Using Haskell with VS Code