Haskellでの id function の用途はどれですか?
高次関数 (関数を引数として取る関数)の引数として、特定の値を変更しないでおくと便利です。
例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関数を渡し、ハッシュ方法として入力します。パフォーマンスのオーバーヘッドはありません。
特に加算と乗算で数値を操作する場合、0と1の有用性に気づくでしょう。同様に、リストを操作する場合、空のリストは非常に便利です。同様に、関数を操作する場合(関数型プログラミングでは非常に一般的)、id
の同じような便利さに気付くでしょう。
関数型言語では、関数はパラメーターとして渡すことができる最初のクラスの値です。したがって、id
の最も一般的な用途の1つは、関数をパラメーターとして別の関数に渡して、何をすべきかを指示するときに現れます。何をするかの選択肢の1つは、「そのままにしておく」ことです。その場合は、id
をパラメーターとして渡します。
各ターンで移動するパズルの解決策を探しているとします。候補者のポジションpos
から始めます。各段階で、pos
に対して可能な変換のリストがあります(たとえば、パズルのピースをスライドさせる)。関数型言語では、変換を関数として表すのが自然なので、関数のリストを使用して移動のリストを作成できます。このパズルで「何もしない」ことが合法である場合、id
でそれを表します。そうしないと、「何もしない」を「何かをする」とは異なる動作をする特別なケースとして処理する必要があります。 id
を使用すると、すべてのケースを単一のリストで均一に処理できます。
これがおそらくid
のほとんどすべての使用法が存在する理由です。 「何もしない」を「何かをする」と一律に扱う。
id
の素敵なアプリケーションを見つけているので。ここに、回文があります:)
import Control.Applicative
pal :: [a] -> [a]
pal = (++) <$> id <*> reverse
また、あなたのゴルフスコアを向上させるお手伝いもできます。使用する代わりに
_($)
_
idを使用して1文字を保存できます。
例えば.
zipWith id [(+1), succ] [2,3,4]
興味深い、有用な結果以上のもの。
別の種類の答え:
これは、コンポジションを介して複数の関数をチェーンするときによく行います。
foo = id
. bar
. baz
. etc
以上
foo = bar
. baz
. etc
編集しやすくなります。次のような他の「ゼロ」要素で同様のことができます
foo = return
>>= bar
>>= baz
foos = []
++ bars
++ bazs
あなたがコンピュータだと想像してください。つまり、一連のステップを実行できます。次に、現在の状態を維持してほしいが、常に指示をしなければならない場合(私は単にミュートして時間を経過させることはできません)、どのような指示を与えますか? Idはそのために作成された関数で、引数を変更せずに戻し(前のコンピューターの場合、引数はその状態になります)、名前を付けます。その必要性は、高次関数があり、関数の内部を考慮せずに関数を操作する場合にのみ現れ、「何もしない」実装でさえも象徴的に表現することを強制します。同様に、0は何かの量と見なされ、量がないことを示す記号です。実際、代数では、0とidの両方がそれぞれ演算+と∘(関数構成)の中立要素と見なされます。
タイプ番号のすべてのxについて:
タイプfunctionのすべてのf:
どこかに関数が必要だが、その場所を保持するだけでは不十分な場合(例として「未定義」を使用)。
(間もなく)スチュワート博士が前述したように、関数を引数として別の関数に渡す必要がある場合にも役立ちます。
join = (>>= id)
または関数の結果として:
let f = id in f 10
(おそらく、上記の関数を後で編集して、より「興味深い」ことを行います...;)
他の人が述べたように、id
は、どこかで関数が必要な場合の素晴らしいプレースホルダーです。