NonEmptyのIsListインスタンスの損なわせる型健全性
結論
OverloadedLists
でNonEmpty
を具体化しない方が良い。
概要
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さんが言っている通り、NonEmpty
のfromList
が悪い(部分関数になっている)。
個人的には、IsList
インスタンスにしないで欲しい。
誘惑に負けてしまう。