1. ホーム
  2. haskell

Haskellの `head` はなぜ空のリストでクラッシュするのか(あるいはなぜ *空のリストを返さないのか)?(言語哲学)

2023-10-22 08:45:05

質問

他の投稿者候補への注意 抽象的な表現、数学的な表現も遠慮なく使ってください。回答が不明確な場合は説明を求めますが、それ以外は自由に表現してください。

はっきり言っておくと、私は ではない を探しているのです。 head を選択したわけでもなく、また head を選択することも、特に例外的に意味があります。質問の要点は headhead' であり、文脈を提供する役割を担っている。

私は数ヶ月間Haskellをハッキングしてきました(私のメイン言語となったほど)。しかし、私はいくつかのより高度な概念や言語の哲学の詳細についてよく知らないことは認めます(学ぶ意欲は十分ありますが)。私の質問は、技術的なものというよりも(技術的であり、私がそれに気づいていないだけであれば)、哲学の1つです。

この例では、私が話しているのは head .

想像するに、ご存知の通りです。

Prelude> head []    
*** Exception: Prelude.head: empty list

これは head :: [a] -> a . 十分公平です。明らかに、(手を振って)型がない要素を返すことはできません。しかし同時に、(些細なことではありますが)単純に

head' :: [a] -> Maybe a
head' []     = Nothing
head' (x:xs) = Just x

という議論を少し見たことがあります。 ここで のコメント欄で少し議論しているのを見かけました。注目すべきは、ある Alex Stangl の発言です。

「すべてを"safe"にせず、前提条件に違反したときに例外を投げるには、それなりの理由があります」。

私は必ずしもこの主張に疑問を持っているわけではありませんが、これらの"good reasons"が何であるのかに興味があります。

さらに、ポール・ジョンソンはこう言っています。

「例えば "safeHead :: [a] -> Maybe a" を定義することができますが、今度は空のリストを処理するか、それが起こりえないことを証明するかではなく、 "Nothing" を処理するか、それが起こりえないことを証明しなければならないのです」。

そのコメントから読み取れるトーンは、これが難易度/複雑さ/何かの顕著な増加であることを示唆していますが、彼がそこに出しているものを私が理解しているかどうかはわかりません。

あるSteven Pruzinaはこう言っています(2011年、以下同)。

"例えば'head'がクラッシュしないようにできないのには、もっと深い理由があります。多相でありながら空のリストを処理するために、'head' は常に特定の空のリストから欠落した型の変数を返さなければなりません。Haskellがそれを実現できれば、Delphicなのですが..."。

空リストの処理を許可することで、ポリモーフィズムは失われるのでしょうか?もしそうなら、どのように、そしてなぜですか?このことを明らかにするような特別なケースがあるのでしょうか? このセクションは @Russell O'Connor によって十分に回答されています。 もちろん、さらなる考えは歓迎されます。

私は、明確さと提案の指示に応じてこれを編集します。どんな考えでも、論文などでも、提供していただけるとありがたいです。

どのように解決するのですか?

<ブロッククオート

空のリストを扱えるようにすると、ポリモーフィズムは失われますか? のリストを処理することによって失われますか?もしそうなら、どのように、そしてなぜですか? このことが明らかになるような特定のケースはありますか? 明らかになりますか?

の自由定理は head は次のように記述します。

f . head = head . $map f

この定理を応用して [] は次のことを意味する。

f (head []) = head (map f []) = head []

この定理は、すべての f に対して成り立つので、特に const Trueconst False . これは

True = const True (head []) = head [] = const False (head []) = False

このように、もし head が適切に多相であり head [] が合計値であった場合 True と同じになる。 False .

PS. あなたの質問の背景について、もしリストが空でないという前提条件があるなら、リストを使う代わりに関数シグネチャで空でないリスト型を使ってそれを強制すべきだという趣旨の他のコメントもあります。