Closed AriFordsham closed 3 years ago
You don't want to go to SOP I
, but rather to SOP Maybe
. hmap Just . from
should do it.
hmap (Just . unI) . from
Can this be used with type families or fundeps?
Given:
class C1 a where
type F a
f1 :: (C1 a) => a -> F a
f1 = undefined
class C2 b a | a -> b where
f2 :: (C2 b a) => a -> b
f2 = undefined
Neither of these compile:
c1 :: (Generic a, C1 a) => a -> SOP f' (Code a)
c1 = hmap (f1 . unI) . from
c2 = hmap (f2 . unI) . from
What is f'
in the lower code block?
There seem to be several problems here. Let's focus on the first example (f1
/ c1
). In c1
, you are first applying from
. At that point you have a SOP I (Code a)
. In order to now map f1 . unI
, you need to know that all the elements of Code a
are members of class C1
. Whether a
itself is is irrelevant. So you need to apply hcmap
. Furthermore, you'd then get an SOP F (Code a)
as a result, but that doesn't work, because type families cannot be partially applied. So you'd either need to make the type family into a data family, or wrap the F
-application in a newtype.
So this would work, for example:
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
module T134 where
import Generics.SOP
class C1 a where
type F a
f1 :: C1 a => a -> F a
f1 = undefined
newtype WrapF a = WrapF (F a)
c1 :: (Generic a, All2 C1 (Code a)) => a -> SOP WrapF (Code a)
c1 = hcmap (Proxy @C1) (WrapF . f1 . unI) . from
The second example is more difficult, because there's no direct relationship between a
and b
except as given by C2
. While this can in principle still be made to work (via htrans
), it's almost certainly not the right approach.
It'd be good to know what you are actually trying to achieve.
Can
generics-sop
be used to map between structures of the same shape but different (but related) types?Imagine I had a record
Rep Record
isSOP I '[ '[Int, String] ]
.I want to map this to
SOP I '[ '[Maybe Int, Maybe String] ]
by wrapping each field inJust
. How would I do this withgenerics-sop
?All the combinators seem to take functions
a -> a
.