Введенный FP: аргументы кортежа и аргументы Curriable

Метод fromJson является относительно новым, как вы можете найти здесь .

В соответствии с этим, вам нужна более новая версия библиотеки или использовать старый Builder, если вы хотите придерживаться своей старой версии.

7
задан harms 2 January 2009 в 00:47
поделиться

5 ответов

Я думаю, что согласие сегодня состоит в том, чтобы обработать несколько аргументов путем приправления карри ( a -> b -> c форма) и зарезервировать кортежи для того, когда Вы действительно хотите значения типа "кортеж" (в списках и так далее). Это согласие уважает каждый функциональный язык со статическим контролем типов начиная со Стандарта ML, который (просто как конвенцию) использует кортежи для функций, которые берут несколько аргументов.

Почему это так? Стандартный ML является самым старым из этих языков, и когда люди сначала писали компиляторы ML, не было известно, как обработать аргументы с приправой карри эффективно. (В корне проблемы то, что любая функция с приправой карри могла быть частично применена некоторым другим кодом, который Вы еще не видели, и необходимо скомпилировать его с той возможностью в памяти.) Начиная со Стандарта ML был разработан, компиляторы улучшились, и можно читать о состоянии в превосходной статье Simon Marlow и Simon Peyton Jones.

LISP, который является самым старым функциональным языком их всех, имеет конкретный синтаксис, который чрезвычайно недружелюбен к приправлению карри и частичному приложению. Hrmph.

7
ответ дан 6 December 2019 в 11:53
поделиться

По крайней мере одна причина не объединить приправленные карри и функциональные типы нес приправой карри состоит в том, что это очень сбивало бы с толку, когда кортежи используются, как возвращается значения (удобный способ на этих типизированных языках для возвращения нескольких значений). В объединенной системе типов, как функция может остаться приятно компонуемой? Был бы a -> (a * a) также преобразуйте к a -> a -> a? Если так, (a * a) -> a и a -> (a * a) тот же тип? В противном случае, как Вы сочинили бы a -> (a * a) с (a * a) -> a?

Вы предлагаете интересное решение проблемы состава. Однако я не нахожу это удовлетворением, потому что это не сцепляется хорошо с частичным приложением, которое является действительно ключевым удобством функций с приправой карри. Позвольте мне попытаться проиллюстрировать проблему в Haskell:

apply f a b = f a b
vecSum (a1,a2) (b1,b2) = (a1+b1,a2+b2)

Теперь, возможно, Ваше решение могло понять map (vecSum (1,1)) [(0,1)], но что относительно эквивалента map (apply vecSum (1,1)) [(0,1)]? Это становится сложным! Ваша самая полная распаковка означает, что эти (1,1) распакован с a apply и b аргументами? Это не намерение... и в любом случае, обоснование становится сложным.

Короче говоря, я думаю, что было бы очень трудно объединить приправленные карри и функции нес приправой карри при (1) сохранении семантики кода, действительного под старой системой и (2) обеспечении разумной интуиции и алгоритма для объединенной системы. Это - интересная проблема, все же.

4
ответ дан 6 December 2019 в 11:53
поделиться

Возможно, потому что полезно иметь кортеж как отдельный тип, и хорошо разделить различные типы?

В Haskell, по крайней мере, довольно легко пойти от одной формы до другого:

Prelude> let add1 a b = a+b
Prelude> let add2 (a,b) = a+b
Prelude> :t (uncurry add1)
(uncurry add1) :: (Num a) => (a, a) -> a
Prelude> :t (curry add2)
(curry add2) :: (Num a) => a -> a -> a

так uncurry add1 то же как add2 и curry add2 совпадает с add1. Я предполагаю, что подобные вещи возможны на других языках также. Чем большие усиления там были бы к автоматическому приправлению карри каждой функции, определяемой на кортеже? (Так как это - то, что Вы, кажется, спрашиваете.)

2
ответ дан 6 December 2019 в 11:53
поделиться

Подробно останавливаясь на комментариях в соответствии с хорошим ответом namin:

Поэтому примите функцию, которая имеет тип 'a -> ('a * 'a):

let gimme_tuple(a : int) =
    (a*2, a*3)

Затем примите функцию, которая имеет тип ('a * 'a) -> 'b:

let add(a : int, b) =
    a + b

Затем состав (принимающий соединение, которое я предлагаю) не создал бы проблемы насколько я вижу:

let foo = add(gimme_tuple(5))
// foo gets value 5*2 + 5*3 = 25

Но затем Вы могли забеременеть полиморфной функции, которая занимает место add в последнем фрагменте кода, например, немного функции, которая просто берет с 2 кортежами и входит в список этих двух элементов:

let gimme_list(a, b) =
    [a, b]

Это имело бы тип ('a * 'a) -> ('a list). Состав теперь был бы проблематичен. Рассмотрите:

let bar = gimme_list(gimme_tuple(5))

Был бы bar теперь имейте значение [10, 15] : int list или был бы bar будьте функцией типа (int * int) -> ((int * int) list), который в конечном счете возвратил бы список, голова которого будет кортежем (10, 15)? Чтобы это работало, я установил в комментарии к ответу namin, что можно было бы быть нужно дополнительное правило в системе типов, что привязка фактических к формальным параметрам быть "самым полным", т.е. что система должна делать попытку нечастичной обязательной первой и единственной попытки частичная привязка, если полная привязка недосягаема. В нашем примере это означало бы, что мы получаем значение [10, 15] потому что полная привязка возможна в этом случае.

Имеет такое понятие "самые полные", по сути бессмысленные? Я не знаю, но я не могу сразу видеть основания, которыми это было бы.

Одна проблема состоит, конечно в том, если бы Вы хотите вторую интерпретацию последнего фрагмента кода, затем необходимо было бы пойти переход через дополнительный обруч (обычно анонимная функция) для получения этого.

2
ответ дан 6 December 2019 в 11:53
поделиться

Кортежи не присутствуют на этих языках просто, чтобы использоваться в качестве параметров функции. Они - действительно удобный способ представить структурированные данные, например, 2D точка (int * int), элемент списка ('a * 'a list), или древовидный узел ('a * 'a tree * 'a tree). Помните также, что структуры являются просто синтаксическим сахаром для кортежей. Т.е.

type info = 
  { name : string;
    age : int;
    address : string; }

удобный способ обработать a (string * int * string) кортеж.

Нет никакой фундаментальной причины, Вам нужны кортежи на языке программирования (можно создать кортежи в лямбда-исчислении, так же, как Вы можете булевские переменные и целые числа — действительно использующий приправляющий карри*), но они удобны и полезны.

* Например,

tuple a b = λf.f a b
fst x     = x (λa.λb.a)
snd x     = x (λa.λb.b)
curry f   = λa.λb.f (λg.g a b)
uncurry f = λx.x f
2
ответ дан 6 December 2019 в 11:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: