[英]Issues with pattern matching and case expression over Data.Typeable.TypeRep
I am trying to pattern match on Data.Typeable.TypeRep in the following code: 我正在尝试在以下代码中对Data.Typeable.TypeRep进行模式匹配:
import Data.Typeable (TypeRep, typeOf)
tyI = typeOf (1 :: Int)
tyD = typeOf (3.14 :: Double)
tyB = typeOf (True :: Bool)
func1 :: TypeRep -> Bool
func1 tyI = False
func1 tyD = False
func1 _ = True
func2 :: TypeRep -> Bool
func2 tr = case tr of
tyI -> False
tyD -> False
_ -> True
func3 :: TypeRep -> Bool
func3 tr = if tr == tyI then False else
if tr == tyD then False else
True
... and I get these warnings on compilation: ...并且在编译时收到以下警告:
[1 of 1] Compiling Main ( /home/[..]/test.hs, interpreted )
/home/[..]/test.hs:8:1: Warning:
Pattern match(es) are overlapped
In an equation for ‘func1’:
func1 tyD = ...
func1 _ = ...
/home/[..]/test.hs:23:12: Warning:
Pattern match(es) are overlapped
In a case alternative:
tyD -> ...
_ -> ...
Ok, modules loaded: Main.
Also, I get the surprising results: 此外,我得到了令人惊讶的结果:
*Main> func1 tyI
False
*Main> func1 tyD
False
*Main> func1 tyB
False -- !!!
*Main> func2 tyI
False
*Main> func2 tyD
False
*Main> func2 tyB
False -- !!!
*Main> func3 tyI
False
*Main> func3 tyD
False
*Main> func3 tyB
True -- Ok!
So only the last function func3 seems to produce the expected results. 因此,似乎只有最后一个函数func3会产生预期的结果。 What should I do to use the pattern matching (func1) and case (func2) functions to work properly over TypeReps?
如何使用模式匹配(func1)和case(func2)函数在TypeReps上正常工作?
The issue is that tyI
and tyD
are being considered as ordinary variables (as opposed to being compared to the global constants of the same name) in the pattern match. 问题在于,在模式匹配中,
tyI
和tyD
被视为普通变量(而不是与同名的全局常量进行比较)。 The code below is completely equivalent to yours. 以下代码与您的代码完全等效。
func1 :: TypeRep -> Bool
func1 x = False
func1 y = False
func1 _ = True
func2 :: TypeRep -> Bool
func2 tr = case tr of
x -> False
y -> False
_ -> True
As you've observed in func3
, the way to solve this is to make the comparison explicit. 正如您在
func3
所观察到的,解决此问题的方法是使比较明确。 You could also do it with guards: 您也可以在卫兵的帮助下进行:
func4 :: TypeRep -> Bool
func4 tr | tr == tyI = False
| tr == tyD = False
| otherwise = True
In general, the only things permitted on the left hand side of the equals against which you can pattern match are constructors. 通常,可以在等号左侧进行模式匹配的唯一条件是构造函数。 The one exception is number literals, and you'll notice that using these in patterns incurs an
Eq
constraint on the function as a whole 一个例外是数字文字,您会注意到,在模式中使用它们会导致整个
Eq
受到Eq
约束
even :: (Num a, Eq a) => a -> Bool
even 0 = True
even 1 = False
even n = even (n-2)
Similar exceptions to this rule are added if you add OverloadedLists
and OverloadedStrings
. 如果添加
OverloadedLists
和OverloadedStrings
则会添加与此规则类似的例外。 The rule still holds for almost all cases. 该规则仍然适用于几乎所有情况。
The tyI
here: 该
tyI
这里:
func1 :: TypeRep -> Bool
func1 tyI = False
has nothing to do with the tyI
defined here: 与
tyI
定义的tyI
无关:
tyI = typeOf (1 :: Int)
In fact, your definition of func1
could have been written: 实际上,您对
func1
的定义可以写成:
func1 :: TypeRep -> Bool
func1 x = False
And the same holds for func2
- the variables tyI
, tyB
and tyD
there are just pattern variable names and do not refer to your global bindings. 对于
func2
同样适用-变量tyI
, tyB
和tyD
存在模式变量名称,并不引用全局绑定。
However, your use of tyI
and tyD
in func3
do refer to the global definitions, so that's why func3 tyB
returns True. 但是,您在
func3
使用tyI
和tyD
确实引用了全局定义,因此这就是func3 tyB
返回True的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.