Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以在Haskell中匹配数据构造函数通配符吗?_Haskell_Pattern Matching - Fatal编程技术网

我可以在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