3

Its inverse seems possible. Since I imagine lists are products and -> is exponentiation, (a*a*a...)^r = (a^r)*(a^r)....

Since we can define the inverse [a->r] -> a -> [r] shouldn't it be possible to define this?

Conal
  • 18,517
  • 2
  • 37
  • 40
user3585010
  • 135
  • 4
  • 8
    How about `const []`? ;) What I mean: what should the function do? –  Sep 03 '14 at 22:36
  • What I was trying to accomplish is, if a function returns a list of values, we should be able to create a list of functions that each of which should capture one index of the list. I was thinking in terms of: f &&& (g &&& (h ... ))) == (f, (g, (h, ...))) – user3585010 Sep 03 '14 at 23:15
  • 1
    The actual algebraic interpretation of lists is that `List A ~ 1 / (1 - A)`, and it does not hold that `1 / (1 - A^R) = (1 / (1 - A))^R` – Gabriella Gonzalez Sep 04 '14 at 21:38
  • [This older answer of mine](http://stackoverflow.com/questions/13765324/haskell-function-from-a-b-a-b/13769761#13769761) might be of interest. – Luis Casillas Sep 05 '14 at 00:48

3 Answers3

8

[a] ≅ a*a*... only holds for infinite lists. For these, your requested function is actually quite simple, though the naïve implementation isn't very efficient:

type InfiList = []

unwind :: (r -> InfiList a) -> InfiList(r -> a)
unwind f = [ \x -> f x !! n | n <- [0..] ]

Actually though, [a] ≅ 1 + a * (1 + a * (1 + ...)); here the power law doesn't work.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • What if the list is finite? We can still define the inverse right? – user3585010 Sep 03 '14 at 22:39
  • @user3585010: you can still define _something_, but it won't be an isomorphism. – leftaroundabout Sep 03 '14 at 22:40
  • 5
    @user3585010: What would you do if the list was finite? For example, let's imagine a function `Int -> [Bool]` that returns `[]` except for `100` where it returns `[True, False]`. What would you expect the resulting `[Int -> Bool]` list to contain? – Tikhon Jelvis Sep 03 '14 at 22:42
  • 5
    It's possible for finite lists of a given size (like `Vec` indexed by a length) or for infinite streams. What they have in common (and `List` does not) is that they can both be expressed as functions from an index set. `Vec n a ≅ Fin n -> a` and `Stream a ≅ Nat -> a`. In that case, the question reduces to calling `flip`. The original question has nothing guaranteeing homogeneity--one value of `r` could result in a list of one length, while another value of `r` could produce a list of a different length. – copumpkin Sep 03 '14 at 22:44
4

If you're willing to fix the size of the list of functions then it'll work.

dn :: [r -> a] -> (r -> [a])
dn fns r = map ($ r)

up :: Int -> (r -> [a]) -> [r -> a]
up n f = tabulate n (\i r -> f' r !! i)
  where 
   f' = cycle . f
   tabulate n f = map f [0..n-1]

Now we can get up as the "sort of" left inverse of dn... provided we shuffle around some length information:

id1 :: [r -> a] -> [r -> a]
id1 ls = up (length ls) (dn ls)

and it can be the "sort of" right inverse of dn if we magically know (a) that for every r the length of the result list [a] is the same and (b) we know that length (called magic below)

id2 :: (a -> [b]) -> a -> [b]
id2 f = dn . up magic

This answer is basically equivalent to copumpkins comment on leftroundabout's answer, but instead of carrying it out using types I'm passing around the (fixed) length information manually. If you play with up and dn for a bit you'll see why this kind of thing won't work for lists in general.

J. Abrahamson
  • 72,246
  • 9
  • 135
  • 180
1

Intuitively, this is impossible if the length of the lists is not known in advance.

This is because the type r -> [a] roughly stands for the following:

  1. Take an input of type r
  2. Output a natural number n (including infinite)
  3. Output a list of n values of type a

As an example, take

replicateA :: Int -> [Char]   -- r = Int , a = Char
replicateA 0 = []
replicateA n = 'A' : replicate (n-1)

By comparison, the type [r -> a] roughly stands for the following:

  1. Output a natural number n (including infinite)
  2. In each of the n elements of the list:
    1. Take an input of type r
    2. Output a value of type a

Here the key fact is that the length of the list must be produced before knowing the r input. This can not be done, in general, since the length can depend on r, as the above replicateA example shows.

chi
  • 111,837
  • 3
  • 133
  • 218