[解決済み] なぜHaskellは "Best Imperative Language "と呼ばれるのか?
疑問点
(この質問がオントピックであることを望みます -- 私は答えを検索しようとしましたが、決定的な答えを見つけられませんでした。もしこれがオフトピックであったり、すでに回答されていたりする場合は、モデレート/削除してください)。
私は、Haskell が 最高の命令型言語 これはもちろん、Haskell が通常その 関数型 機能でよく知られているからです。
そこで質問ですが、Haskellのどのような品質や特徴が、Haskellがとみなされることを正当化する理由となるのでしょうか? 最高の命令型言語 -- それとも冗談のようなものでしょうか?
どのように解決するのですか?
私は半分真実だと考えています。 Haskellは素晴らしい抽象化能力を持っていて、それは命令的な考えに対する抽象化も含んでいます。 例えば、Haskellには命令的なwhileループは組み込まれていませんが、それを書けば、今はそうなっています。
while :: (Monad m) => m Bool -> m () -> m ()
while cond action = do
c <- cond
if c
then action >> while cond action
else return ()
このレベルの抽象化は多くの命令型言語では困難です。 PythonやC#のようなクロージャを持つ命令型言語では可能です。
しかし、Haskellは(非常にユニークな)次のような能力も持っています。 許容される副作用を特徴づける モナドクラスを使用します。 たとえば、ある関数があるとします。
foo :: (MonadWriter [String] m) => m Int
これは "imperative"関数である可能性がありますが、2つのことしかできないことが分かっています。
- 文字列のストリームを出力する。
- Intを返す
コンソールへのプリントやネットワーク接続の確立などはできません。 抽象化能力と組み合わせることで、"ストリームを生成するあらゆる計算"に作用する関数などを書くことができます。
Haskellが非常に優れた命令型言語であるのは、本当にHaskellの抽象化能力によるものなのです。
しかし、その半面、構文に問題があります。 Haskellはかなり冗長で、命令文スタイルで使うには厄介だと思います。 以下は、上記を使った命令型スタイルの計算の例です。
while
ループを使って、リンクリストの最後の要素を見つける命令型スタイルの計算の例です。
lastElt :: [a] -> IO a
lastElt [] = fail "Empty list!!"
lastElt xs = do
lst <- newIORef xs
ret <- newIORef (head xs)
while (not . null <$> readIORef lst) $ do
(x:xs) <- readIORef lst
writeIORef lst xs
writeIORef ret x
readIORef ret
IORef のゴミ、二重読み込み、読み込みの結果をバインドしなければならないこと、fmapping (
<$>
) を使ってインライン計算の結果を操作しなければならない......すべてが非常に複雑に見えます。 からは全く意味がありません。
機能的
の観点からは非常に理にかなっていますが、命令型言語では使いやすくするためにこれらの詳細のほとんどを隠してしまう傾向があります。
確かに、もし私たちが別の
while
-スタイルのコンビネータを使用すれば、よりきれいになることは確かです。 しかし、その哲学を十分に発揮すれば(豊富なコンビネータを使って自分自身を明確に表現すれば)、再び関数型プログラミングにたどり着きます。 命令型スタイルのHaskellは、よく設計された命令型言語(たとえばpython)のように、quot;flow"ではないだけです。
結論として、Haskellは構文を一新することで、最高の命令型言語となる可能性があります。 しかし、フェイスリフトの性質上、それは内部的に美しく本当のものを、外部的に美しく偽のものに置き換えることになります。
EDIT
: コントラスト
lastElt
をこのpythonの音訳と比較してみてください。
def last_elt(xs):
assert xs, "Empty list!!"
lst = xs
ret = xs.head
while lst:
ret = lst.head
lst = lst.tail
return ret
同じ行数ですが、各行のノイズはかなり少なくなっています。
編集2
参考までに、このように ピュア の置換がどのように見えるかです。
lastElt = return . last
これで終わりです。あるいは、もしあなたが、私に
Prelude.last
:
lastElt [] = fail "Unsafe lastElt called on empty list"
lastElt [x] = return x
lastElt (_:xs) = lastElt xs
あるいは、任意の
Foldable
のデータ構造で動作させ、実際には
は必要ありません。
IO
を使用して、エラーを処理します。
import Data.Foldable (Foldable, foldMap)
import Data.Monoid (Monoid(..), Last(..))
lastElt :: (Foldable t) => t a -> Maybe a
lastElt = getLast . foldMap (Last . Just)
で
Map
のように、例えば
λ➔ let example = fromList [(10, "spam"), (50, "eggs"), (20, "ham")] :: Map Int String
λ➔ lastElt example
Just "eggs"
は
(.)
演算子は
関数構成
.
関連
-
[解決済み】haskellでリストを逆順にする
-
[解決済み] Haskell Preludeの'const'は何のためにあるのか?
-
[解決済み] .の違いは何ですか?(ドット)と$(ドルマーク)の違いは何ですか?
-
[解決済み] フリーモナドとは何ですか?
-
[解決済み] Haskellで副作用がモナドとしてモデル化されているのはなぜですか?
-
[解決済み] Haskellにはなぜ "data "と "newtype "があるのですか?重複] [重複] [重複
-
[解決済み] TLSサーバーを実装するためのHsOpenSSL APIの適切な使用法
-
[解決済み] Haskellの "Just "構文とは?
-
[解決済み] HaskellとF#の主な違いは何ですか?[クローズド]
-
[解決済み] Lazy I/Oの何がそんなに悪いのか?
最新
-
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 Preludeの'const'は何のためにあるのか?
-
[解決済み] Haskellです。パターンでのパースエラー
-
[解決済み] ghciで関数を複数行に渡って定義するには?
-
[解決済み] Haskellにはなぜ "data "と "newtype "があるのですか?重複] [重複] [重複
-
[解決済み] 無限リストでのfoldlとfoldrの動作
-
[解決済み] なぜ遅延評価が有効なのか?
-
[解決済み] リストからn番目の要素を得るには?
-
[解決済み] Haskellのドット演算子:もっと説明が欲しい
-
[解決済み] このHaskellのコードはなぜ-Oをつけると遅くなるのですか?