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インスタンスにしないで欲しい。 誘惑に負けてしまう。

筆者プロフィール

my-latest-logo

aiya000(あいや)

せつラボ 〜圏論の基本〜」 「せつラボ2~雲と天使と関手圏~」 「矢澤にこ先輩といっしょに代数!」を書いています!

強い静的型付けとテストを用いて、バグを防ぐのが好き。Haskell・TypeScript。