1

I´m trying to learn more about dependent types using IDRIS. The example I am trying to emulate uses composition of Vectors. I understand Functor and Applicative implementations for Vectors but I am struggling to implement them for the Composition.

data Vector : Nat -> Type -> Type where
    Nil : Vector Z a
    (::) : a -> Vector n a -> Vector (S n) a

Functor (Vector n) where
    map f [] = []
    map f (x::xs) = f x :: map f xs

Applicative (Vector n) where
    pure = replicate _
    fs <*> vs = zipWith apply fs vs

Now the Composition and Decomposition-Function look like this:

data (:++) : (b -> c) -> (a -> b) -> a -> Type where
    Comp : (f . g) x -> (f :++ g) x

unComp : (f :++ g) a -> (f . g) a
unComp (Comp a) = a

User with Vectors it encapsulates a Vector of Vectors. Now I need an Applicative for the Composition (Vector n) :++ (Vector n). I can´t even get Functor to work and am mainly trying to see what I´m doing wrong. I tried the following and, since Functor is already implemented for Vectors, that this would work

Functor ((Vector n) :++ (Vector n)) where
    map f (Comp [])        = Comp []
    map f (Comp (x::xs))   = Comp ((f x) :: (map f (Comp xs)))

but the Compiler gives an Error-Message:

When checking an application of constructor Main.:::
        Unifying a and Vector (S n) a would lead to infinite value

Isn´t unifying and element of type a and a Vector n a exactly the purpose of (::)? I am obviously doing something wrong and I can´t get this to work. I also have the feeling it´s probably easy to solve, but after hours of reading and trying I still don´t get it. If someone could give me advice or explain to me how the Functor and Applicative implementations could look like, I would be very grateful.

Illuia
  • 11
  • 1

1 Answers1

1

Update: Idris 2 now has this builtin. Functor for Compose, Applicative for Compose

I think you can implement a general instance of Functor and Applicative like with Haskell's Compose.

newtype Compose f g a = Compose { getCompose :: f (g a) }

instance (Functor f, Functor g) => Functor (Compose f g) where
    fmap f (Compose x) = Compose (fmap (fmap f) x)
    a <$ (Compose x) = Compose (fmap (a <$) x)

instance (Applicative f, Applicative g) => Applicative (Compose f g) where
    pure x = Compose (pure (pure x))
    Compose f <*> Compose x = Compose (liftA2 (<*>) f x)
    liftA2 f (Compose x) (Compose y) =
      Compose (liftA2 (liftA2 f) x y)

To answer your specific question (but don't do it this way):

Functor ((Vector n) :++ (Vector n)) where
    map f (Comp x) = Comp $ map (map f) x
michaelmesser
  • 3,601
  • 2
  • 19
  • 42