[Haskell-cafe] Modifying a product type generically

Aleksey Khudyakov alexey.skladnoy at gmail.com
Fri Jan 2 21:03:54 UTC 2015

> Wow, thanks, this is almost exactly what I've been looking for. My next
> trick was going to be to combine "convert", "cons", and "tail" operations.
> From your example, we can `cons` an "A" to a Foo to get a BigFoo:
>   > H.cons "A" (Foo 1 2) :: BigFoo
>   BigFoo "A" 1 2
> And we can `tail` a BigFoo to get a Foo:
>   > H.tail (BigFoo "Hello" 1 2) :: Foo
>   Foo 1 2
> But if I combine the two, GHC doesn't know what to do:
>   > H.cons "A" (H.tail (BigFoo "Hello" 1 2)) :: BigFoo
>   <interactive>:15:1:
>       Couldn't match type ‘H.Elems v0’ with ‘'[Int, Int]’
>       The type variable ‘v0’ is ambiguous
>       Expected type: [Char] : H.Elems v0
>         Actual type: H.Elems BigFoo
>       In the expression:
>         H.cons "A" (H.tail (BigFoo "Hello" 1 2)) :: BigFoo
>       In an equation for ‘it’:
>         it = H.cons "A" (H.tail (BigFoo "Hello" 1 2)) :: BigFoo
> I can make it work in this case by supplying a type signature for the
> intermediate `tail` expression -- but what if there is no such type? Can
> I trick it into deducing any old type with the right shape? An
> intermediate tuple would work, for example.
This is problem inherent to very generic code. There could be too many
types which could be assigned to intermediate extression. GHC deduce
that intermediate type must be isomorphic to (Int,Int) but could not chose
such type.

We however can always create vector with elements of right type. Library
works by converting values to Boehm-Berarducci encoding (ContVec),
perform operations on and convert back to concrete representation.
So we can fix type of intermediate vector to `ContVec xs` and let GHC
to figure out rest. So following will work:

> import qualified Data.Vector.HFixed.Cont as H (ContVec)
> asCont :: H.ContVec a -> H.ContVec a
> asCont = id

*Main> (H.cons "A" . asCont . H.tail) (BigFoo "Hello" 1 2) :: BigFoo
BigFoo "A" 1 2

This function is not in the library but I'm going to add it. It is usefult for
combining functions

More information about the Haskell-Cafe mailing list