[解決済み] Haskellにおける "リフティング "とは?
質問
リフティングとは何ですか?まず、モナドを理解してから、"lift"が何であるかを理解すべきですか?(私もモナドについて全く無知です :) それとも、どなたか簡単な言葉で説明していただけませんか?
どのように解決するのですか?
リフティングは数学的概念というより、デザインパターンです(今頃、誰かがリフティングがカテゴリか何かであることを示して、私に反論すると思いますが)。
一般的に、あるデータ型とパラメータがあるとします。 次のようなものです。
data Foo a = Foo { ...stuff here ...}
が多く使われていることが分かったとします。
Foo
は数値型を取る (
Int
,
Double
など)、これらの数値をラップから外し、足したりかけたりして、ラップに戻すコードを書き続けなければなりません。 これを回避するには、ラップを解除してラップするコードを一度書けばよい。 この関数は伝統的にリフトと呼ばれ、次のように表示されます。
liftFoo2 :: (a -> b -> c) -> Foo a -> Foo b -> Foo c
つまり、2つの引数をとる関数(たとえば
(+)
演算子)をFoosの等価関数に変換する。
ということで、次のように書けるようになりました。
addFoo = liftFoo2 (+)
編集:詳細情報
もちろん
liftFoo3
,
liftFoo4
などがあります。しかし、これは必要ない場合が多い。
観察から始める
liftFoo1 :: (a -> b) -> Foo a -> Foo b
しかし、これでは全く同じ
fmap
. だから、むしろ
liftFoo1
と書くことになります。
instance Functor Foo where
fmap f foo = ...
もし、本当に完全な規則性を求めるのであれば、次のようにすることができます。
liftFoo1 = fmap
を作ることができれば
Foo
をファンクタにすることで、おそらく応用ファンクタにすることができます。実際、もしあなたが
liftFoo2
とすると、アプリケーティブなインスタンスは次のようになります。
import Control.Applicative
instance Applicative Foo where
pure x = Foo $ ... -- Wrap 'x' inside a Foo.
(<*>) = liftFoo2 ($)
は
(<*>)
演算子で、Foo は
(<*>) :: Foo (a -> b) -> Foo a -> Foo b
ラップした値に対してラップした関数を適用するのです。そのため、もし
liftFoo2
であれば、それを参考に書くことができます。あるいは、直接これを実装して
liftFoo2
というのは
Control.Applicative
モジュールには
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
があり、同様に
liftA
と
liftA3
. しかし、実際には別の演算子があるので、あまり使うことはないでしょう。
(<$>) = fmap
これで書くことができます。
result = myFunction <$> arg1 <*> arg2 <*> arg3 <*> arg4
用語
myFunction <$> arg1
はFooでラップされた新しい関数を返します。
ghci> :type myFunction
a -> b -> c -> d
ghci> :type myFunction <$> Foo 3
Foo (b -> c -> d)
これを次の引数に適用するには、次のようにします。
(<*>)
といった具合です。つまり、すべてのアリティにリフト関数があるのではなく、次のような応用のデイジーチェーンがあるだけなのです。
ghci> :type myFunction <$> Foo 3 <*> Foo 4
Foo (c -> d)
ghci: :type myFunction <$> Foo 3 <*> Foo 4 <*> Foo 5
Foo d
関連
-
[解決済み】なぜパースエラーになるのか?インデント?
-
[解決済み] 末尾再帰とは何ですか?
-
[解決済み] (関数型)リアクティブプログラミングとは?
-
[解決済み] Hindley-Milnerのどの部分が理解できないのでしょうか?
-
[解決済み】ミュータブルステートなしで何か役に立つことができるのか?
-
[解決済み】Haskellの入門編
-
[解決済み】Haskell/GHCの`forall`キーワードは何をするのですか?
-
[解決済み] Haskellのマルチコアプログラミングはどうなっているのか?
-
[解決済み] Haskellでメモ化?
-
[解決済み] レコードの単一フィールドを割り当て、残りのフィールドはコピーするための省略記法?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 一般的に `{- |` で始まるHaskellのコメントは何を意味するのですか?
-
[解決済み] Haskell - Ord aの型は何を意味するのでしょうか?
-
[解決済み] モナドはエンドファンクタのカテゴリではただのモノイドですが、何か問題でも?
-
[解決済み] RustのtraitとHaskellのtypeclassの違いは何ですか?
-
[解決済み] Haskellにはなぜ "data "と "newtype "があるのですか?重複] [重複] [重複
-
[解決済み] 制約条件付き特殊化
-
[解決済み] Haskell における `mod` と `rem` の違い
-
[解決済み] GHCはなぜこんなに大きいのか/大きいのか?
-
[解決済み] CabalとStackの違いは何ですか?
-
[解決済み] TLSサーバーを実装するためのHsOpenSSL APIの適切な使用法