How do I say an instance of B
could be made for those m
s that are instances of A
but say nothing about other m
s:
-- A.hs
module A where
class A m -- m :: * -> *
-- B.hs, totally unrelated to A
module B where
class B m
-- Utilities.hs
module Utilities where
given A m then instance B m -- like given in Scala 3
Please note I do not want to say :
class A => class B -- B requires A
The B
does not and should not know about A
. At the class
level B
has nothing to do with A
. B
is defined solely in terms of its Minimal Complete Definition which is expressed after its where
clause (not show here) and has no knowledge of A
or any other class. In fact B
is standalone.
I also do not want to say :
instance A m => B m -- *all* m are B, this requires A m as well
-- actually this errors out with a "constraint is no smaller than head"
-- which is fixed by `newtype`ing around the `m` in `B`
-- but this is besides the point
This says all m
s are B
s and also requires that all m
also be A
s which is not true and not what I want to say. This is not what the Scala line (blow) is saying.
What I want to say is exactly this:
There is a B
, it defines a certain interface. There is also an totally unrelated A
. B
is not defined in terms of A
nor does it require A
in any way at its definition site.
Now someone else comes along and knows a way to make an instance of B
for an m
if there is an instance of A
for it.
In Scala I could easily say:
implicit def fromA[M: A]: B[M] = ...
This is saying if you can prove that M
is an A
(in Scala this is achieved by bringing an implicit
A[M]
into scope) then I can automatically construct B
instances for M
. In particular this does not force B
on all M
s and is not an error if A[M]
does not hold for some M
. You are at liberty to construct B
for an M
all by yourself. The (second) Haskell code above is not equivalent to this Scala code.
I'm looking for an equivalent in Haskell
UPDATE Apparently there is no way to do this in Haskell
UPDATE 2 This is the concrete case behind this question Can't code my component in a tagless-final way / using type classes and instances