dvi*_*tek 3 rational-number haskell pattern-matching rational-numbers
以下函数非常简单:
test :: Int -> Int
test x = case x of
0 -> 0
1 -> 1
_ -> 2
Run Code Online (Sandbox Code Playgroud)
事实上,test 0 == 0和test 1 == 1,和test 77 == 2.
以下功能几乎一样简单:
import Data.Ratio
test2 :: Rational -> Int
test2 = case x of
0 -> 0
1 % 2 -> 1
_ -> 2
Run Code Online (Sandbox Code Playgroud)
在GHCi中加载此代码会出错Parse error in pattern: 1 % 2.
是什么赋予了?为什么我不能在有理数上进行模式匹配?我可以解决这个例子来自卫兵的现实问题,但我很好奇为什么模式匹配不起作用.
通常,您不能在函数上进行模式匹配.这将需要计算逆,这通常甚至不存在.你只能匹配构造类似Just或:+:这些都是普通函数/缀运营商识别用大写字符或冒号开始.
你可以在理性上进行模式匹配.
import GHC.Real (:%)
test2 :: Rational -> Int
test2 = case x of
0 -> 0
1 :% 2 -> 1
_ -> 2
Run Code Online (Sandbox Code Playgroud)
我想,为什么不建议使用:%它(因此它只是从内部模块而不是从内部模块导出Data.Ratio)的原因是Ratio值总是应该是最小的,但是:%作为普通构造函数不能确保:
Prelude Data.Ratio GHC.Real> 4%2
2 % 1
Prelude Data.Ratio GHC.Real> 4:%2
4 % 2
Run Code Online (Sandbox Code Playgroud)
特别是,如果您实际上在这样的非标准化分数上进行模式匹配,则无法确定是否成功.
在类似情况下1%2,您可以通过小数部分上的模式匹配来规避问题(有限小数部分是唯一的):
test2 :: Rational -> Int
test2 = case x of
0 -> 0
0.5 -> 1
_ -> 2
Run Code Online (Sandbox Code Playgroud)
当然,这可能不是那么好.在现代Haskell中,理论上可以将其重新定义:%为智能模式的同义词:
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
import Data.Ratio
numDenum :: Integral a => Ratio a -> (a,a)
numDenum x = (numerator x, denominator x)
pattern (:%) :: () => Integral a => a -> a -> Ratio a
pattern a:%b <- (numDenum -> (a,b))
where a:%b = a%b
Run Code Online (Sandbox Code Playgroud)
然后可以在原始示例中使用它.
......但坦率地说,它可能会更好只使用numerator和denominator,因为它们.