我可以在Haskell中匹配数据构造函数通配符吗?
我有 并定义了我可以在Haskell中匹配数据构造函数通配符吗?,haskell,pattern-matching,Haskell,Pattern Matching,我有 并定义了 data Foo = X (String, Int) | A String | B String | C String | D String -- ... 但是我更愿意写一些像 f (X (s, _)) =s f (A s) = s f (B s) = s f (C s) = s f (D s) = s -- ... 但似乎并没有办法做到这一点(我得到了一个与\uu相关联的“解析错误”) 有没有办法匹配Haskell中的数据构造函数通配符?没有。但你可以这样写: f (X
data Foo = X (String, Int) | A String | B String | C String | D String -- ...
但是我更愿意写一些像
f (X (s, _)) =s
f (A s) = s
f (B s) = s
f (C s) = s
f (D s) = s
-- ...
但似乎并没有办法做到这一点(我得到了一个与\uu
相关联的“解析错误”)
有没有办法匹配Haskell中的数据构造函数通配符?没有。但你可以这样写:
f (X (s, _)) =s
f (_ s) = s
然后有name::Foo->String
。你也可以考虑这个:
data Foo
= X { name :: String, age :: Int }
| A { name :: String }
| B { name :: String }
| C { name :: String }
| D { name :: String }
除了@DanielWagner的答案外,还有一种替代方法是使用(也称为“SYB”)。它允许您查找给定类型的第一个子项。所以你可以定义
data Tag = A | B | C | D
data Foo = X String Int | Tagged Tag String
f (X s _) = s
f (Tagged _ s) = s
而fooString
将返回构造函数的第一个String
参数。函数筛选出字符串
s并获取所有立即子项的筛选值
但是,这不会从X
返回字符串
,因为X
没有立即字符串
子项,它只有一个(String,Int)
类型的子项。要获取术语层次结构中任何位置的第一个字符串
,可以使用:
请注意,这种方法有点脆弱:它只包括它找到的所有
字符串,这可能并不总是您想要的,特别是,如果您以后扩展您的数据类型(或它引用的某个数据类型)。我猜方法的选择(我使用的方法与您的第二种方法相比)取决于“标记”的数量有一个。在实践中,我只有几个(并且有更多的构造函数具有稍微不同的形式),我认为我的方法可能是最干净的。选择这三种方法中的一种而不是另一种方法有概念上的原因吗?@raxacoricofallapatorius哪种方法有意义很大程度上取决于您希望类型的含义——就像您在某些情况下编写2*1+2*2+2*3
和2*(1+2+3)
在其他例子中,为了强调对数字感兴趣的不同原因,12
@raxacoricocfallapatorius,如果字符串在每种情况下代表相同的东西,那么标记方法是有意义的。如果字符串不相关,则可能需要三个构造函数。事实上,你想对字符串做同样的事情,但这并不意味着标记的方法是有意义的。虽然语言中没有这样的东西(除了你可以考虑使用或生成这样的代码)。你的用例是否合理?
{-# LANGUAGE DeriveDataTypeable #-}
import Control.Monad
import Data.Data
import Data.Generics.Schemes
import Data.Typeable
data Foo = X (String, Int) | A String | B String | C String | D String
deriving (Show, Eq, Ord, Data, Typeable)
fooString :: Foo -> Maybe String
fooString = msum . gmapQ cast
fooString' :: Foo -> Maybe String
fooString' = everything mplus cast