我有一个函数,在给定数据类型的情况下输出类似booleanlike的属性。此函数通过模式匹配在数据类型的第一个构造函数上计算属性,所以类似于
data C = C1 | C2 | .. | Cn
f :: C -> Bool
f (C1 _ _ ... _) = True
f (C2 _ _ ... _) = True
f (C3 _ _ ... _) = False
.
.
.
f (Cn _ _ ..._) = False
是否有更紧凑的方式来执行模式匹配,还是有另一种(也更紧凑)的方式来进行我的财产检查?我不想将属性添加到数据类型定义中,因为它可以相对容易地计算。
答案 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语句保存一些输入,但不多。
如果我们有更多关于您试图解决的问题的详细信息(例如,您的数据的另一种表示是否有一些输出模式)也许还有另一种方法。