Можно ли на хаскеле написать функцию: (r -> [a]) -> [r -> a])?

Его обратное кажется возможным. Поскольку я представляю, что списки — это продукты, а -> — это возведение в степень, (a*a*a...)^r = (a^r)*(a^r)....

Поскольку мы можем определить обратное [a->r] -> a -> [r], не должно ли быть возможно определить это?


person user3585010    schedule 03.09.2014    source источник
comment
Как насчет const []? ;) Что я имею в виду: что должна делать функция?   -  person    schedule 04.09.2014
comment
Что я пытался сделать, так это то, что если функция возвращает список значений, мы должны иметь возможность создать список функций, каждая из которых должна захватывать один индекс списка. Я думал в терминах: f &&& (g &&& (h ... ))) == (f, (g, (h, ...)))   -  person user3585010    schedule 04.09.2014
comment
Фактическая алгебраическая интерпретация списков состоит в том, что List A ~ 1 / (1 - A), и она не верна, что 1 / (1 - A^R) = (1 / (1 - A))^R   -  person Gabriel Gonzalez    schedule 05.09.2014
comment
Этот мой старый ответ может представлять интерес.   -  person Luis Casillas    schedule 05.09.2014


Ответы (3)


Если вы хотите исправить размер списка функций, это сработает.

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]

Теперь мы можем получить up как "своего рода" левую инверсию dn... при условии, что мы перемешаем некоторую информацию о длине:

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

и это может быть «своего рода» правая инверсия dn, если мы волшебным образом знаем (а), что для каждого r длина списка результатов [a] одинакова, и (б) мы знаем эту длину (называемую magic ниже)

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

Этот ответ в основном эквивалентен комментарию copumpkins к ответу leftroundabout, но вместо того, чтобы выполнять его с использованием типов, я передаю информацию о (фиксированной) длине вручную. Если вы немного поиграете с up и dn, вы поймете, почему такие вещи не работают для списков в целом.

person J. Abrahamson    schedule 04.09.2014

[a] ≅ a*a*... справедливо только для бесконечных списков. Для них запрошенная вами функция на самом деле довольно проста, хотя реализация нефа не очень эффективна:

type InfiList = []

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

На самом деле, [a] ≅ 1 + a * (1 + a * (1 + ...)); здесь степенной закон не работает.

person leftaroundabout    schedule 03.09.2014
comment
Что делать, если список конечен? Мы все еще можем определить обратное право? - person user3585010; 04.09.2014
comment
@ user3585010: вы все еще можете определить что-то, но это не будет изоморфизмом. - person leftaroundabout; 04.09.2014
comment
@ user3585010: Что бы вы сделали, если бы список был конечным? Например, давайте представим функцию Int -> [Bool], которая возвращает [], за исключением 100, где она возвращает [True, False]. Что, по-вашему, должен содержать полученный список [Int -> Bool]? - person Tikhon Jelvis; 04.09.2014
comment
Это возможно для конечных списков заданного размера (например, Vec, индексированных по длине) или для бесконечных потоков. Что у них общего (а у List нет), так это то, что обе они могут быть выражены как функции из набора индексов. Vec n a ≅ Fin n -> a и Stream a ≅ Nat -> a. В этом случае вопрос сводится к звонку flip. В исходном вопросе нет ничего, гарантирующего однородность: одно значение r может привести к списку одной длины, а другое значение r может привести к списку другой длины. - person copumpkin; 04.09.2014

Интуитивно это невозможно, если длина списков заранее не известна.

Это связано с тем, что тип r -> [a] примерно означает следующее:

  1. Возьмите ввод типа r
  2. Выведите натуральное число n (в том числе бесконечное)
  3. Вывести список из n значений типа a

В качестве примера возьмем

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

Для сравнения, тип [r -> a] примерно означает следующее:

  1. Выведите натуральное число n (в том числе бесконечное)
  2. In each of the n elements of the list:
    1. Take an input of type r
    2. Вывести значение типа a

Ключевым фактом здесь является то, что длина списка должна быть получена прежде, чем будет известно входное значение r. В общем случае это невозможно, поскольку длина может зависеть от r, как показано в приведенном выше примере replicateA.

person chi    schedule 04.09.2014