Контроль функции арности - PullRequest
1 голос
/ 03 марта 2012

Я читал ответ на этот вопрос: Haskell: разница между. (точка) и $ (знак доллара) И ответ показался мне странным ... Что он имеет в виду + не имеет ввода? И тогда я попробовал:

((+) 1)
((+) 1 1)
((+) 1 1 1)

Упс ... грустные новости. Но я уверен, что видел функции, которые могут принимать, казалось бы, произвольные или очень большое количество аргументов, чтобы полагать, что кто-то определил их способом a-> b-> c ...-> z. Должен быть какой-то способ справиться с этим! Я ищу что-то вроде & rest или & option в CL.

Ответы [ 2 ]

11 голосов
/ 03 марта 2012

Конечно, вы можете определить функцию сложения с вариациями с помощью некоторого хакерского типа: 1

{-# LANGUAGE TypeFamilies #-}

class Add r where
    add' :: (Integer -> Integer) -> r

instance Add Integer where
    add' k = k 0

instance (n ~ Integer, Add r) => Add (n -> r) where
    add' k m = add' (\n -> k (m+n))

add :: (Add r) => r
add = add' id

И так:

GHCi> add 1 2 :: Integer
3
GHCi> add 1 2 3 :: Integer
6

Тот же трюк используется стандартным модулем Text.Printf. Обычно этого избегают по двум причинам: во-первых, с типами, с которыми он работает, работать неудобно, и вам часто приходится указывать явную сигнатуру типа для вашего использования; во-вторых, это действительно взлом, и его следует использовать редко, если вообще. printf должен принимать любое количество аргументов и быть полиморфными, поэтому он не может просто взять список списков, но для дополнения вы можете просто использовать sum.

1 Расширение языка здесь не является строго необходимым, но оно облегчает использование (без них вам пришлось бы явно указывать тип каждого аргумента в приведенных мной примерах, например add (1 :: Integer) (2 :: Integer) :: Integer). * * тысячу двадцать-один

2 голосов
/ 03 марта 2012

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

Предположим, у вас есть функция foo, которая допускает арность 1 или 2, и рассмотрите следующее выражение:

foo a b

Если 1 или2 аргумент версии Foo будет использоваться здесь?Компилятор не может знать, как это может быть версия с двумя аргументами, но в равной степени это может быть результатом версии с одним аргументом, примененной к b.

Следовательно, разработчикам языка необходимо сделать выбор.

  • Haskell выбирает приятный синтаксис приложения функции (круглые скобки не требуются)
  • Lisp выбирает переменные функции арности (и добавляет круглые скобки для удаления неоднозначности)
...