# 083: litpattern.hs で renPat: LitExp (LitInteger 0 (1,3)) [↑up](bunny_notes) - issued: 2020-05-18 - 分類: A サンプルコードが fail - status: Closed (2020-05-20) ## 概要 lib/Prelude.hs に gcd を定義しようとして発覚。 パターンに整数リテラルを書くとエラー。 litpattern.hs $$
{
f 0 = "zero"
f _ = "non-zero"
main = do putStrLn $ f 1
putStrLn $ f 0
$$}
類似: litpattern2.hs, litpattern3.hs
なお、似ているが case 式の場合には異る箇所でエラーしたため、
別 issue ([084](bissue084)) とした。
## 概要
## 2020-05-18
最初、リテラルを疑似コンストラクタで表現するのかなとも思ったが、
Bounded とはいえ値の個数がおおく(それはなんとかしたとしても)、
数値リテラルは多相なので、うまくいきそうにない。
そのことを考慮すると、
== 演算子をもちいるような形に desuger してやるしかないのではないか。
参考として、GHC がどうしているのかを、
${ghc -ddump-ds-preopt testcases/litpattern.hs} で確認:
$${
f :: forall a. (Eq a, Num a) => a -> [Char]
[LclId]
f = \ (@ a_a211)
($dEq_a2hL :: Eq a_a211)
($dNum_a2hM :: Num a_a211) ->
let {
$dNum_a2ds :: Num a_a211
[LclId]
$dNum_a2ds = $dNum_a2hM } in
let {
$dEq_a212 :: Eq a_a211
[LclId]
$dEq_a212 = $dEq_a2hL } in
letrec {
f_a2du :: a_a211 -> [Char]
[LclId]
f_a2du
= \ (ds_d2kK :: a_a211) ->
let {
fail_d2l2 :: GHC.Prim.Void# -> [Char]
[LclId]
fail_d2l2
= \ (ds_d2l3 [OS=OneShot] :: GHC.Prim.Void#) ->
GHC.CString.unpackCString# "non-zero"# } in
case ==
@ a_a211 $dEq_a212 ds_d2kK (fromInteger @ a_a211 $dNum_a2ds 0)
of wild_00 {
False -> fail_d2l2 GHC.Prim.void#;
True -> GHC.CString.unpackCString# "zero"#
}; } in
f_a2du
$$}
単純化すると、次のように書き換えているようだ (litpattern-ds.hs):
$${
f = \x ->
let
fail' = "non-zero"
in
case (==) x 0 of
False -> fail'
True -> "zero"
$$}
fail の内容が変数に束縛されていて、複数の個所から呼べるように(上の例では一か所だが)なっているのが、変換のヒントのように見える。
どういうアルゴリズムでこのように変換するかは、考えどころ。
なんとなくだが、以下のように変換してから [064](bissue064)
の問題と統一的に扱うのが良い気がする。
$${
f x | x == 0 = "zero"
f _ = "non-zero"
$$}
## 2020-05-19
まず、↑のように ${f x | x == 0 = "zero"} のような形の式をただしく扱えるようにする。
現状では、Rename の時点で FAIL を ${error "Error: Non-exhaustive patterns."}
におとしてしまっていたので、これを、Prim.FAIL とする。
さらに、TrCore にて、transExpr (Fatbar e f) とあった場合に、e, f それぞれを
Core に直したうえで、e にあった FAIL を f を変換したものに置き換えるようにした。
これで、この形の式は通るようになった。
つぎは、${f 0 = ...} を ${f x | x == 0 = ...} に変換すればいいはず。
## 2020-05-20
renDecl にて、いままでどおりのリネームを行うまえに、左辺のパターンに
リテラルがあった場合には、上述のような変換をするようにした。これにより、
想定していたケースには対応、本件はクローズとする。
A.Exp のすべてに対応しないといけないわけではないはずだが、仕様を確認して、
必要十分な対処になっているかどうかは確認したい。これは、別 issue ([086](bissue086))
とする。
また、litpattern2.hs では、浮動小数点リテラルに未対応なのでコケてしまった。
これも、別問題なので新規 issue ([087](bissue087)) とする。
lib/Prelude.hs において、本件のためにコメントアウトしてあった、gcd, lcm, (^) の定義は復活。
- litpattern.hs: sample217.hs
- litpattern3.hs: sample218.hs
- gcdlcm.hs: sample219.hs