Применить список значений в качестве аргументов к функции

Могу ли я применить список из n значений к функции, которая принимает n значений, где n варьируется?

Первая наивная попытка заключается в следующем, но компилятор (справедливо) жалуется на weird self-referential type for applyN

applyN f xs =
    case xs of
        [] -> f
        (x::xs) -> applyN (f x) xs

Я не понимаю, как будет работать сгиб, и уважать его подпись типа.

Для контекста я хочу взять список декодеров N Json и оценить

Json.objectN ConstructorN n1 n2 ... nN

Ясно, что если n известно (скажем, 2), то мы имеем

case lst of
    (d1 :: d2 :: _) -> Json.object2 Constructor2 d1 d2
    otherwise -> ....

но это много кода писать, если я не могу обобщить для n.

Я боюсь, что это невозможно, так как в Haskell это нужны специальные флаги компилятора.


elm
person Simon H    schedule 07.12.2015    source источник
comment
Вы возвращаете функцию? [] -> ф. Мне это кажется странным, но я, честно говоря, не знаю.   -  person mac10688    schedule 07.12.2015
comment
Ага. ApplyN все неправильно. Но мне нужно предложение   -  person Simon H    schedule 07.12.2015
comment
Итак, вы пытаетесь выполнить фолд. Какой вы хотите, чтобы возвращаемый тип был в функции? Список вещей или какой-то тип? Кстати, я не знаю Elm и сейчас изучаю Haskell. Потерпите меня, если я не в себе.   -  person mac10688    schedule 07.12.2015
comment
Я знаю, что если вы хотите вернуть список, в базовом случае легко вернуть пустой список. Но если вы пытаетесь создать один объект, я упускаю из виду, что вам следует делать. Что, если ваш базовый случай совпадет с одним элементом, а не с пустым списком? Вот так, [x::[]] -> f x   -  person mac10688    schedule 07.12.2015
comment
Вы также упомянули фолд, но я думаю, что фолд должен иметь аккумулятор. Вот почему трудно выяснить, что вы хотите вернуть для базового случая. Сгиб будет соответствовать пустому списку и вернет аккумулятор.   -  person mac10688    schedule 07.12.2015


Ответы (2)


В этом контексте декодирования Json, если у вас есть литерал списка с декодерами, вы можете сделать что-то эквивалентное applyN. В этом шаблоне используются функции map: (a -> b) -> Decoder a -> Decoder b и andMap : Decoder (a -> b) -> Decoder a -> Decoder b. Вы используете его так:

Constructor
  `Json.map` n1
  `Json.andMap` n2
  `Json.andMap` ...
  `Json.andMap` nN

К сожалению, andMap не предлагается для каждого основного модуля. Вы можете определить это самостоятельно, если есть map2 или andThen. В этом случае работает object2. , это в основном то же самое, что и map2. Так:

andMap : Decoder (a -> b) -> Decoder a -> Decoder b
andMap decFun decA =
  object2 (\f a -> f a) decFun decA

Вы также можете использовать Json.Decode.Extra.apply , то же самое, только названное нестандартным образом*.

*в любом случае нестандартно в мире Elm

person Apanatshka    schedule 10.12.2015
comment
OMG: используйте тот факт, что парсеры являются аппликативными. Невыразимо умный - person Simon H; 10.12.2015
comment
Будет ли это работать для TupleX - я думаю, что нет, поскольку Tuple сразу проверяет длину массива, поэтому вы не можете постепенно работать над ним? - person Simon H; 12.12.2015

Нет, вы не можете этого сделать, по крайней мере, без зависимых типов или, по крайней мере, некоторых трюков на уровне типов, которых нет в Elm (для справки: Как мне определить применение Lisp в Haskell?)

(Кстати, именно поэтому существуют все функции objectN.)

Попробуйте реструктурировать свой код — нельзя ли f просто взять список?

person Philip Kamenarsky    schedule 07.12.2015