21

arity :: a -> Integer任意の関数のアリティを決定する関数を書くことは可能ですか?

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

?

4

6 に答える 6

26

はい、非常に簡単に実行できます。

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

理由: 関数の場合、正確に 1 つの引数に適用できます。haskell 構文では、0 個、2 個、またはそれ以上の引数をそのままの形で適用することはできないことに注意f a b(f a) bf applied to a and bください(f applied to a) applied to b。もちろん、その結果は、再度適用できる別の関数になる可能性があります。

ばかげているように聞こえますが、真実に他なりません。

于 2011-12-03T17:57:15.207 に答える
18

それは簡単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) 

Upd問題が見つかりました。ポリモーフィック関数には非ポリモーフィック タイプを指定する必要があります。

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

これを解決する方法はまだわかりません。

Upd2 as Sjoerd Visscher が以下にコメントしたように、「答えは選択したタイプに依存するため、非ポリモーフィック タイプを指定する必要があります」。

于 2011-12-03T16:55:13.607 に答える
11

idアリティが 1 の場合、id xアリティが 0 であってはなりませんか? しかし、たとえば、あなたの例ではアリティ2を持つid mapと同じです。map

次の関数のアリティは同じですか?

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

「アリティ」の概念が明確に定義されていないと思います...

于 2011-12-03T16:43:11.867 に答える
3

Haskell では、すべての「関数」は厳密に 1 つの引数を取ります。「複数引数」関数のように見えるものは、実際には 1 つの引数を取り、残りの引数を取る別の関数を返す関数です。その意味で、すべての関数のアリティは 1 です。

于 2011-12-03T21:27:21.413 に答える
2

標準の Haskell では不可能です。IncoherentInstances または同様の拡張機能を使用すると、可能になる場合があります。

しかし、なぜこれをしたいのですか?関数に期待する引数の数を尋ね、この知識を使用して正確にその数の引数を与えることはできません。(テンプレート Haskell を使用している場合を除きます。その場合は、はい、コンパイル時に可能であると思います。テンプレート Haskell を使用していますか?)

あなたが解決しようとしている実際の問題は何ですか?

于 2011-12-03T16:42:42.997 に答える
1

これはどう:

arity :: a -> Int
arity (b->c) = 1 + arity (c)
arity _ = 0
于 2011-12-05T07:46:55.750 に答える