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

StackOverflow https://stackoverflow.com/questions/8369114

  •  27-10-2019
  •  | 
  •  

Вопрос

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

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

?

Это было полезно?

Решение

Это легко с 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 ниже: «Вы должны указать неполиморфный тип, так как ответ зависит от того, какой тип вы выберете».

Другие советы

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

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. Анкет Результат, конечно, может быть еще одной функцией, которую можно применить снова, и так далее.

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

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

Есть ли следующие функции одинаковой артистики?

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

Я думаю, что ваше представление о «Arity» не четко определена ...

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

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

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

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

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

arity :: a -> Int
arity (b->c) = 1 + arity (c)
arity _ = 0
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top