2016-05-05 5 views
2

Я пытаюсь выяснить причины и следствие логики позади «Карринг» и приходит к следующим результатам:Почему Haskell принимает один аргумент

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

Я думаю, что приведенная выше логика 1 -> 2 -> 3 сбивает с толку ответ «зачем использовать каррирование». Для оператора 3 также можно комбинировать несколько кортежей или списков в качестве единственного аргумента для реализации функции множества аргументов.

Кажется, что утверждение 1 является неправильной причиной для утверждения 2. То, что я уверен, является 2-> 3 правильным аргументом, но в чем причина 2? Почему Haskell, как функциональный язык, принимает только один аргумент?

Большинство книг принимают заявление 2 как общепринятый факт. Кто-нибудь знает причину 2? Или кто-нибудь знает правильную логику «почему карри»?

+0

Вы спрашиваете: «Зачем использовать currying?», Что подразумевает, что в какой-то момент кто-то подумал: «Давайте использовать currying для решения проблемы дизайна языка, который у нас есть». Но на самом деле этого не произошло. Кто-то подумал: «Давайте сделаем простой, элегантный, выразительный, удобный, безопасный и гибкий язык». Решениями этих проблем являются использование лямбда-исчисления с индуктивными типами, хорошая система типов и несколько необычная стратегия сокращения. «Использовать каррирование» - это не решение какой-либо одной из этих проблем, а скорее случайный инструмент в системе, который решает эти проблемы. –

+0

Если вы думаете о кортежах, подобных типам товаров (например: «Bool» имеет двух жителей: «Возможно, у Bool» три человека, «(Bool, Maybe Bool)» имеет шесть жителей), тогда типы функций являются показателями. Поскольку 'e^(x * y) = (e^x)^y', вы всегда можете переписать функцию с типом' (x, y) -> e' в аналогичную функцию с типом 'y -> (x - > e) '. Это вкратце. Поскольку вы всегда можете переписать такие функции (в данном случае, при относительно низкой стоимости), вам не нужно * делать многопараметрические функции фундаментальной концепцией, которая в противном случае усложняла бы ваше определение языка. –

ответ

1

Прежде всего, вы должны помнить, что Haskell полностью основан на исчислении лямбда. Это сделано по модели научного программирования (хотя это не означает, что язык имеет только научные возможности).

Что я думаю, что вы ошибаетесь, это не единственный аргумент, потому что его можно показать как кортеж или список, хотя это было бы довольно умное объяснение.

Haskell принимает только один аргумент, потому что каррирования:

Р (х, у) = Р (х) (у)

где Р (х) возвращает функцию, которая принимает один аргумент. Currying - это целая схема «Функции, возвращающая функции». Итак, когда вы f (x) (y), вы фактически передаете «y» в функцию «f (x)».

Классический пример:

add :: a->(a->a) 
add(x) = x'+' 

Поскольку '+' является функцией, которая означает, что она принимает один аргумент, мы можем:

add(3)(5) == 8 

Мы не передавая оба аргумента в добавить , только один, чтобы он мог генерировать '+', который получает другой аргумент.

После того, как вы поймете, что будет иметь большой смысл, и мы можем продолжить, почему.

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

add = '+' 

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

Здесь есть хорошие ответы с хорошими примерами: https://softwareengineering.stackexchange.com/questions/185585/what-is-the-advantage-of-currying

+0

Спасибо за ваше напоминание о том, что Haskell основывается на исчислении lamda. Я прошел исчисление лямбда и нашел ответ, который, как я думаю, довольно близок: во-первых, вычисление lamda с использованием его определения доказано универсальным в том смысле, что все вычисления могут быть выраженный им с точки зрения marthmatics. Во-вторых, одно из лямбда-определения - каждая функция принимает только один аргумент. Затем, как лямбда-исчисление может быть заявлено универсальным, если оно не может представлять множество функций аргументов. Ответ, конечно, может быть, только с помощью Curryring (функция высокого порядка). – Johnson

+0

Да, вы получили это довольно хорошо. – eduardogbg

2

Функция

f x y = x + y 

имеет тип (предполагая, что x & y являются Integer ы)

f :: Integer -> Integer -> Integer 

это то же самое, как

g :: Integer -> (Integer -> Integer) 

Это означает f является функцией что принимает Integer и возвращает новую функцию, которая также принимает Integer и возвращает Integer. Currying - это процесс, при котором функция, которая принимает несколько аргументов, фактически оценивается как ряд функций, которые принимают один аргумент.

Каррирование делает его очень легко частично применить функции следующим образом

plusTwo :: Integer -> Integer 
plusTwo = f 2 

приведенный выше код просто применяется к 2f и связывает имя plusTwo к полученной функции.

Это очень упрощает разработчикам абстрактное поведение в одном месте.

4

Решения использовать каррирование в качестве предпочтительного метода функций нескольких аргументов был сделан по двум причинам. Во-первых, у Haskell есть свои корни в лямбда-исчислении, которое использует каррирование. Во-вторых, каррирование допускает легкое частичное применение, фасет языка, который неописуемо полезен.

Смежные вопросы