简体   繁体   English

通过Data.Typeable.TypeRep进行模式匹配和大小写表达式的问题

[英]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. 问题在于,在模式匹配中, tyItyD被视为普通变量(而不是与同名的全局常量进行比较)。 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 . 如果添加OverloadedListsOverloadedStrings则会添加与此规则类似的例外。 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同样适用-变量tyItyBtyD存在模式变量名称,并不引用全局绑定。

However, your use of tyI and tyD in func3 do refer to the global definitions, so that's why func3 tyB returns True. 但是,您在func3使用tyItyD确实引用了全局定义,因此这就是func3 tyB返回True的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM