如何根据类型类值进行模式匹配?

Mai*_*tor 3 haskell typeclass

假设我在Haskell中定义一个类型类,

class (Bool a) where
    false :: a
    true  :: a
Run Code Online (Sandbox Code Playgroud)

为了定义任何通用not操作Bool,需要对其潜在值进行模式匹配:

not :: Bool a => a ? a
not true  = false
not false = true
Run Code Online (Sandbox Code Playgroud)

但是,这不会编译.我怎样才能让它发挥作用?

Tik*_*vis 5

你无法匹配像这样的类型类值.类型抽象超过实际的底层类型,而模式匹配会暴露它.

但是,您仍然可以使用ViewPatterns扩展名获得相同的行为和一些很好的语法.我们的想法是包含一个函数,它接受您的抽象值,并为您提供表示结构视图的具体类型的值:

class (Bool a) where
  true   :: a
  false  :: a
  asBool :: a -> Bool
Run Code Online (Sandbox Code Playgroud)

现在,您可以将asBool模式匹配中的函数用作视图模式:

not :: Bool a => a -> a
not (asBool -> True)  = false
not (asBool -> False) = true
Run Code Online (Sandbox Code Playgroud)

但是,请注意,这可能导致asBool计算两次,如果它隐藏了昂贵的计算,则可能是一个问题.

  • @pigworker"当在函数定义或case表达式的多个分支中应用相同的视图函数时(例如,上面的大小),GHC尝试将这些应用程序收集到单个嵌套的case表达式中,以便view函数是只申请一次." 虽然有限制,但上述情况应该可以正常进行. (3认同)
  • @ØrjanJohansen事实上,它需要编译器巫毒来解决其后果,这表明它可能是一种错误.最好明确做一次计算. (3认同)