Haskell替代长模式匹配列表?

时间:2014-02-20 11:34:20

标签: haskell pattern-matching

我有一个函数,在给定数据类型的情况下输出类似booleanlike的属性。此函数通过模式匹配在数据类型的第一个构造函数上计算属性,所以类似于

data C = C1 | C2 | .. | Cn 

f :: C -> Bool 
f (C1 _ _ ... _) = True
f (C2 _ _ ... _) = True
f (C3 _ _ ... _) = False
.
.
.
f (Cn _ _ ..._) = False

是否有更紧凑的方式来执行模式匹配,还是有另一种(也更紧凑)的方式来进行我的财产检查?我不想将属性添加到数据类型定义中,因为它可以相对容易地计算。

5 个答案:

答案 0 :(得分:8)

您可以使用记录语法来避免使用通配符模式。另外,使用case表达式以避免重复函数名称,例如

f :: C -> Bool
f x = case x of
  C1 {} -> True
  C2 {} -> False
  ...
  Cn {} -> False

这就像在不改变数据类型的情况下那样紧凑。

答案 1 :(得分:6)

此外,只需列出True个或False个,具体取决于您拥有的内容,并将多数结果设为默认值:

f C1{} = True
f C42{} = True
f _ = False                 -- all others false

答案 2 :(得分:2)

您可能需要查看toConstr in the Data.Data模块。这可以为您提供构造函数的表示,然后您可以根据需要进行分析(即转换为String,或从中获取索引)。

答案 3 :(得分:1)

基于@ yatima的回答,你可以做这样的事情

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Char
import Data.Data

data C = C1 Int
       | C2 Int
       | C3 Int
       | C4 Int
       deriving (Data,Typeable)

f :: C -> Bool
f c = let [_,n] = show (toConstr c) in digitToInt n < 3

然后在GHCI

>> f (C1 0)
True
>> f (C2 0)
True
>> f (C3 0)
False
>> f (C4 0)
False

答案 4 :(得分:-1)

也许:

f (x _ _ ... _) = g x where
  g C1 = True
  g C2 = True
  g C3 = False
  .
  .
  .
  g Cn = False

您可以使用case语句保存一些输入,但不多。

如果我们有更多关于您试图解决的问题的详细信息(例如,您的数据的另一种表示是否有一些输出模式)也许还有另一种方法。