Given the following type family (supposed to reflect the isomorphism A×1 ≅ A)
type family P (x :: *) (a :: *) :: * where
P x () = x
P x a = (x, a)
and data type defined in terms thereof
data T a = T Integer (P (T a) a)
is it possible by some type hackery to write a Functor
instance for the latter?
instance Functor T where
fmap f = undefined -- ??
Intuitively, it's obvious what to do depending on the type of f
, but I don't know how to express it in Haskell.
I tend to reason about these kind higher kind programs using Agda.
The problem here is that you want to pattern match on *
(Set
in Agda), violate parametericity, as mentioned in the comment. That is not good, so you cannot just do it. You have to provide witness. I.e. following is not possible
P : Set → Set → Set
P Unit b = b
P a b = a × b
You can overcome the limitiation by using aux type:
P : Aux → Set → Set
P auxunit b = b
P (auxpair a) b = a × b
Or in Haskell:
data Aux x a = AuxUnit x | AuxPair x a
type family P (x :: Aux * *) :: * where
P (AuxUnit x) = x
P (AuxPair x a) = (x, a)
But doing so you'll have problems expressing T
, as you need to pattern match on its parameter again, to select right Aux
constructor.
"Simple" solution, is to express T a ~ Integer
when a ~ ()
, and T a ~ (Integer, a)
directly:
module fmap where
record Unit : Set where
constructor tt
data ⊥ : Set where
data Nat : Set where
zero : Nat
suc : Nat → Nat
data _≡_ {ℓ} {a : Set ℓ} : a → a → Set ℓ where
refl : {x : a} → x ≡ x
¬_ : ∀ {ℓ} → Set ℓ → Set ℓ
¬ x = x → ⊥
-- GADTs
data T : Set → Set1 where
tunit : Nat → T Unit
tpair : (a : Set) → ¬ (a ≡ Unit) → a → T a
test : T Unit → Nat
test (tunit x) = x
test (tpair .Unit contra _) with contra refl
test (tpair .Unit contra x) | ()
You can try to encode this in Haskell to.
You can express it using e.g. 'idiomatic' Haskell type inequality
I'll leave the Haskell version as an exercise :)
Hmm or did you meant by data T a = T Integer (P (T a) a)
:
T () ~ Integer × (P (T ()) ())
~ Integer × (T ())
~ Integer × Integer × ... -- infinite list of integers?
-- a /= ()
T a ~ Integer × (P (T a) a)
~ Integer × (T a × a) ~ Integer × T a × a
~ Integer × Integer × ... × a × a
Those are easier to encode directly as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With