web-dev-qa-db-ja.com

Haskell id関数の使用

Haskellでの id function の用途はどれですか?

60
fjsj

高次関数 (関数を引数として取る関数)の引数として、特定の値を変更しないでおくと便利です。

例1:Justにある場合は値をそのままにし、それ以外の場合はデフォルトの7を返します。

Prelude Data.Maybe> :t maybe
maybe :: b -> (a -> b) -> Maybe a -> b

Prelude Data.Maybe> maybe 7 id (Just 2)
2

例2:フォールドを介して関数を作成:

Prelude Data.Maybe> :t foldr (.) id [(+2), (*7)]
:: (Num a) => a -> a

Prelude Data.Maybe> let f = foldr (.) id [(+2), (*7)]

Prelude Data.Maybe> f 7
51

fを基本ケースとして使用して、関数のリストを(.)と一緒に折りたたむことにより、新しい関数idを作成しました。

例3:モノイドとしての関数の基本ケース(簡略化)。

instance Monoid (a -> a) where
        mempty        = id
        f `mappend` g = (f . g)

フォールドを使用した例と同様に、関数は連結可能な値として扱うことができ、idは空のケースに対応し、(.)は追加として処理されます。

例4:簡単なハッシュ関数。

Data.HashTable> h <- new (==) id :: IO (HashTable Data.Int.Int32 Int)

Data.HashTable> insert h 7 2

Data.HashTable> Data.HashTable.lookup h 7
Just 2

ハッシュテーブルにはハッシュ関数が必要です。しかし、キーがすでにハッシュされている場合はどうでしょうか?次に、id関数を渡し、ハッシュ方法として入力します。パフォーマンスのオーバーヘッドはありません。

80
Don Stewart

特に加算と乗算で数値を操作する場合、0と1の有用性に気づくでしょう。同様に、リストを操作する場合、空のリストは非常に便利です。同様に、関数を操作する場合(関数型プログラミングでは非常に一般的)、idの同じような便利さに気付くでしょう。

69
Conal

関数型言語では、関数はパラメーターとして渡すことができる最初のクラスの値です。したがって、idの最も一般的な用途の1つは、関数をパラメーターとして別の関数に渡して、何をすべきかを指示するときに現れます。何をするかの選択肢の1つは、「そのままにしておく」ことです。その場合は、idをパラメーターとして渡します。

21
Yitz

各ターンで移動するパズルの解決策を探しているとします。候補者のポジションposから始めます。各段階で、posに対して可能な変換のリストがあります(たとえば、パズルのピースをスライドさせる)。関数型言語では、変換を関数として表すのが自然なので、関数のリストを使用して移動のリストを作成できます。このパズルで「何もしない」ことが合法である場合、idでそれを表します。そうしないと、「何もしない」を「何かをする」とは異なる動作をする特別なケースとして処理する必要があります。 idを使用すると、すべてのケースを単一のリストで均一に処理できます。

これがおそらくidのほとんどすべての使用法が存在する理由です。 「何もしない」を「何かをする」と一律に扱う。

6
sigfpe

idの素敵なアプリケーションを見つけているので。ここに、回文があります:)

import Control.Applicative

pal :: [a] -> [a]
pal = (++) <$> id <*> reverse
3
raichoo

また、あなたのゴルフスコアを向上させるお手伝いもできます。使用する代わりに

_($)_

idを使用して1文字を保存できます。

例えば.

zipWith id [(+1), succ] [2,3,4]

興味深い、有用な結果以上のもの。

3
mrehayden

別の種類の答え:

これは、コンポジションを介して複数の関数をチェーンするときによく行います。

foo = id
  . bar
  . baz
  . etc

以上

foo = bar
  . baz
  . etc

編集しやすくなります。次のような他の「ゼロ」要素で同様のことができます

foo = return
  >>= bar
  >>= baz

foos = []
  ++ bars
  ++ bazs
3
Thomas Eding

あなたがコンピュータだと想像してください。つまり、一連のステップを実行できます。次に、現在の状態を維持してほしいが、常に指示をしなければならない場合(私は単にミュートして時間を経過させることはできません)、どのような指示を与えますか? Idはそのために作成された関数で、引数を変更せずに戻し(前のコンピューターの場合、引数はその状態になります)、名前を付けます。その必要性は、高次関数があり、関数の内部を考慮せずに関数を操作する場合にのみ現れ、「何もしない」実装でさえも象徴的に表現することを強制します。同様に、0は何かの量と見なされ、量がないことを示す記号です。実際、代数では、0とidの両方がそれぞれ演算+と∘(関数構成)の中立要素と見なされます。

タイプ番号のすべてのxについて:

  • 0 + x = x
  • x + 0 = x

タイプfunctionのすべてのf:

  • id∘f = f
  • f∘id = f
3
lamg

どこかに関数が必要だが、その場所を保持するだけでは不十分な場合(例として「未定義」を使用)。

(間もなく)スチュワート博士が前述したように、関数を引数として別の関数に渡す必要がある場合にも役立ちます。

join = (>>= id)

または関数の結果として:

let f = id in f 10

(おそらく、上記の関数を後で編集して、より「興味深い」ことを行います...;)

他の人が述べたように、idは、どこかで関数が必要な場合の素晴らしいプレースホルダーです。

0
BMeph