Подтвердить что ты не робот

Haskell: функция определения арности функций?

Можно ли написать функцию arity :: a -> Integer, чтобы определить арность произвольных функций, такую, что

> arity map
2
> arity foldr
3
> arity id
1
> arity "hello"
0

?

4b9b3361

Ответ 1

Легко с OverlappingInstances:

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}

class Arity f where
  arity :: f -> Int

instance Arity x where
  arity _ = 0

instance Arity f => Arity ((->) a f) where
  arity f = 1 + arity (f undefined) 

Обновление. Для полиморфных функций вам необходимо указать неполиморфный тип:

arity (foldr :: (a -> Int -> Int) -> Int -> [a] -> Int)

Не знаю, как это решить.

Upd2, как прокомментировал Sjoerd Visscher ниже, "вы должны указать неполиморфный тип, поскольку ответ зависит от того, какой тип вы выберете".

Ответ 2

Да, это можно сделать очень, очень легко:

arity :: (a -> b) -> Int
arity = const 1

Обоснование: если это функция, вы можете применить ее к точно одному аргументу. Обратите внимание, что синтаксис haskell делает невозможным применение к 0, 2 или более аргументам, поскольку f a b действительно (f a) b, то есть не f applied to a and b, а (f applied to a) applied to b. Результатом может быть, конечно, еще одна функция, которую можно применить снова и т.д.

Звучит глупо, но это не что иное, как правда.

Ответ 3

Если id имеет arity 1, не должно id x иметь arity 0? Но, например, id map идентичен map, который имеет в вашем примере arity 2.

Имеют ли следующие функции одинаковые свойства?

f1 = (+)
f2 = (\x y -> x + y)
f3 x y = x + y

Я думаю, что ваше понятие "arity" не совсем определено...

Ответ 4

Это невозможно со стандартным Haskell. Это может быть возможно с использованием IncoherentInstances или аналогичного расширения.

Но почему вы хотите это сделать? Вы не можете спросить функцию, сколько аргументов она ожидает, а затем использовать это знание, чтобы дать ему именно такое количество аргументов. (Если вы не используете Template Haskell, в этом случае, да, я ожидаю, что это возможно во время компиляции. Используете ли вы Template Haskell?)

Какова ваша фактическая проблема, которую вы пытаетесь решить?

Ответ 5

В Haskell каждая "функция" принимает ровно один аргумент. То, что выглядит как функция с несколькими аргументами, фактически является функцией, которая принимает один аргумент и возвращает другую функцию, которая принимает остальные аргументы. Таким образом, в этом смысле все функции имеют arity 1.

Ответ 6

Как насчет этого:

arity :: a -> Int
arity (b->c) = 1 + arity (c)
arity _ = 0