galaxy-sixth-sensey - NonEmptyのIsListインスタンスの損なわせる型健全性
2017/10/12
NonEmptyのIsListインスタンスの損なわせる型健全性

結論

 OverloadedListsNonEmptyを具体化しない方が良い。

概要

In haskell-jp slack

igrep [18:25]
OverloadedLists, 意外と怖いですね。うっかりNonEmptyに対して空リストを使ってしまうとランタイムエラーになっちゃうみたいで。。。

>>> :set -XOverloadedLists
>>> import qualified Data.List.NonEmpty as NE
>>> [] :: NonEmpty Int
*** Exception: NonEmpty.fromList: empty list
>>> [] :: [Int]
[]

理論的にはコンパイル時に fromList を実行してコンパイルエラーにできそうなもんですし、惜しい。

 OverloadedLists拡張はOverloadedStrings拡張と似た構造をしていて、 型Set, Map, そしてNonEmpty

 例えば以下のコードはコンパイルを通り、実行時エラーになる。

{-# LANGUAGE OverloadedLists #-}

import Data.List.NonEmpty (NonEmpty(..))

f :: NonEmpty Int -> Int
f (x:|_) = x + 1

main :: IO ()
main = print $ f []
-- {output}
-- xxx.hs: NonEmpty.fromList: empty list

 igrepさんが言っている通り、NonEmptyfromListが悪い(部分関数になっている)。


 個人的には、IsListインスタンスにしないで欲しい。 誘惑に負けてしまう。


この記事はこちらから修正リクエストを送ることができます。
NonEmptyのIsListインスタンスの損なわせる型健全性 - github
ゴミ箱ボタンの左にある、鉛筆ボタンを押してね!