ご存知の通り(?)、PureScriptはHaskell風の構文を持ったAltJSです。しかし、あくまでHaskell「風」であるため、パッと見た限りでは全く同じに見える構文でも実際に書いてみると思わぬ違いに遭遇することがあります。
ガード節とwhereの組み合わせ
たとえばHaskellで書かれたこんなコードがあります。 (Wandboxで実行)
若干わざとらしいコードですが、ガード節にまたがるwhereで定義した変数を見て、ガード節を使ってその値によって分岐をしています。
compareWith10 :: Int -> String
compareWith10 n
| c == LT = show n <> "は10より小さいです。"
| c == EQ = show n <> "は10です。"
| c == GT = show n <> "は10より大きいです。"
| otherwise = "ありえないです。"
where
c = n `compare` 10
PureScriptでもそのまま動きそうなコードに見えます。しかし、実際に実行してみると・・・(Try PureScript!で実行)
こんなエラーが出ます。
Unknown value c
そうなんです。PureScriptでは、whereで定義した変数はガード節をまたぐことはできないのです。
PureScriptでのwhereのスコープ
whereで定義した変数がガード節をまたぐことができない一方で、PureScriptでは個々のガード節にwhereを書けます。 (Try PureScript!で実行)
compareWith10 :: Int -> String
compareWith10 n
| n `compare` 10 == LT = show n <> s where s = "は10より小さいです。"
| n `compare` 10 == EQ = show n <> s where s = "は10です。"
| n `compare` 10 == GT = show n <> s where s = "は10より大きいです。"
| otherwise = show s where s = "ありえないです。"
Haskellではこのコードはコンパイルできません。 (Wandboxで実行)
Issue
この「whereで定義した変数がガード節をまたげない」という問題、GitHubにissueが無いか探してみたら、3年以上前からありました。
Move where clauses under guards · Issue #888 · purescript/purescript
個人的にとても不便なので、このまま放置され続けるようなら最悪自分で直せないかと考えながらPureScriptコンパイラのソースを読んだりしています。