Frage

Ist es möglich, eine Funktion zu schreiben? arity :: a -> Integer um die Arität beliebiger Funktionen zu bestimmen, so dass

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

?

War es hilfreich?

Lösung

Es ist einfach mit 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) 

Aktualisierung Problem gefunden. Sie müssen den nicht polymorphen Typ für polymorphe Funktionen angeben:

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

Ich weiß noch nicht, wie ich das lösen soll.

Upd2 Wie SJOERD Visscher nachstehend kommentierte, "müssen Sie einen nicht polymorphen Typ angeben, da die Antwort davon abhängt, welchen Typ Sie auswählen".

Andere Tipps

Ja, es kann sehr, sehr leicht gemacht werden:

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

Begründung: Wenn es sich um eine Funktion handelt, können Sie sie auf genau 1 Argument anwenden. Beachten Sie, dass die Haskell -Syntax es unmöglich macht, auf 0, 2 oder mehr Argumente als zu bewerben f a b ist wirklich (f a) b, dh nicht f applied to a and b, aber (f applied to a) applied to b. Das Ergebnis kann natürlich eine weitere Funktion sein, die wieder angewendet werden kann und so weiter.

Klingt dumm, ist aber nichts als die Wahrheit.

Wenn id hat Arity 1, sollte nicht id x haben Arity 0? Aber zum Beispiel, id map ist identisch mit map, was Arity 2 in Ihrem Beispiel hätte.

Haben Sie die folgenden Funktionen dieselbe Arität?

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

Ich denke, Ihre Vorstellung von "Arity" ist nicht gut definiert ...

In Haskell nimmt jede "Funktion" genau ein Argument. Was wie eine "Multi-Argument" -Funktion aussieht, ist tatsächlich eine Funktion, die ein Argument nimmt und eine andere Funktion zurückgibt, die den Rest der Argumente übernimmt. In diesem Sinne haben alle Funktionen Arity 1.

Mit Standard-Haskell ist das nicht möglich.Möglicherweise ist die Verwendung von IncoherentInstances oder einer ähnlichen Erweiterung möglich.

Aber warum willst du das tun?Sie können eine Funktion nicht fragen, wie viele Argumente sie erwartet, und dieses Wissen dann nutzen, um ihr genau diese Anzahl an Argumenten zu geben.(Es sei denn, Sie verwenden Template Haskell. In diesem Fall gehe ich davon aus, dass dies zur Kompilierungszeit möglich ist.Verwenden Sie Template Haskell?)

Was ist Ihr eigentliches Problem, das Sie lösen möchten?

Wie wäre es damit:

arity :: a -> Int
arity (b->c) = 1 + arity (c)
arity _ = 0
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top