2016-08-22 30 views
0

我试图模式匹配上Data.Typeable.TypeRep以下代码:问题与模式匹配和情况下表达过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 

...和我得到的编译这些警告:

[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. 

而且,我得到了令人惊讶的结果:

*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! 

所以只有最后一个功能FUNC3 SE ems产生预期的结果。我应该如何使用模式匹配(func1)和case(func2)函数在TypeReps上正常工作?

+2

使用'-Wall'启用更多警告:在这种情况下,还应该报告全局绑定与本地绑定的阴影,以进一步了解您的问题。 – chi

+1

'TypeRep'应该会在GHC 8.2中发生大的变化。如果发生这种情况,你可能会发现它比现在更有用。 – dfeuer

回答

3

问题是tyItyD被视为模式匹配中的普通变量(与相同名称的全局常量相比)。下面的代码与您的代码完全相同。

func1 :: TypeRep -> Bool 
func1 x = False 
func1 y = False 
func1 _ = True 

func2 :: TypeRep -> Bool 
func2 tr = case tr of 
    x -> False 
    y -> False 
    _ -> True 

正如你在func3已经观察到,要解决这个办法是作出比较明确的。你也可以用后卫做到这一点:

func4 :: TypeRep -> Bool 
func4 tr | tr == tyI = False 
     | tr == tyD = False 
     | otherwise = True 

一般情况下,对上你可以模式匹配的构造等号的左边允许的唯一的东西。唯一的例外是数字文字,你会发现,在模式使用这些招对功能的Eq约束作为一个整体

如果添加 OverloadedListsOverloadedStrings
even :: (Num a, Eq a) => a -> Bool 
even 0 = True 
even 1 = False 
even n = even (n-2) 

类似的例外添加。该规则对于几乎所有情况仍然适用。

+0

谢谢。无论如何,你会碰巧知道在TypeReps的代码中是否有引用“同名全局常量”的方法?是否有任何TypeRep肠胃药物?例如“Typeable.Int”,“Typeable.Bool”?我在文档中看不到任何内容(http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Typeable.html)。我认为这可以让我保持模式匹配功能。否则,我会坚持func4风格。 – Janthelme

+1

不,没有希望这条大道 - “TypeRep”是有目的的不透明的(没有构造函数导出)。真的'func4'是你最好的选择。 :) – Alec

3

tyI这里:

func1 :: TypeRep -> Bool 
func1 tyI = False 

无关与这里定义的tyI

tyI = typeOf (1 :: Int) 

事实上,你的func1定义可以这样写:

func1 :: TypeRep -> Bool 
func1 x = False 

同样适用于func2 - 变量tyI,tyBtyD只有模式变量名称,并没有引用您的全局绑定。

不过,您的func3使用tyItyD做参考全局定义,所以这就是为什么func3 tyB返回true。