考虑以下几点:在Haskell中,有没有办法在构造函数上使用参数做“elem”?
data A = A1 | A2 Integer
x = [A1, A2 999]
elem A1 x == True
有没有办法做下面的测试?
elem (A2 _) x == True
考虑以下几点:在Haskell中,有没有办法在构造函数上使用参数做“elem”?
data A = A1 | A2 Integer
x = [A1, A2 999]
elem A1 x == True
有没有办法做下面的测试?
elem (A2 _) x == True
instance Eq A where
A1 == A1 = True
A2 _ == A2 _ = True
_ == _ = False
elem (A2 undefined) x == True
当然,这具有超出您要求的效果。
在我的例子中,我认为([z |(A2 z)< - x]/= [])是最简单的,因为我只需要使用它一次,但我相信定义A的一个实例可能最恰当的选择。谢谢,ephemient。 – me2 2010-02-01 02:06:24
@ me2:不要使用'/ = []';相反,使用'不。 null'。有关基本原理,请参阅http://www.haskell.org/haskellwiki/Haskell_programming_tips#Don.27t_ask_for_the_length_of_a_list_when_you_don.27t_need_it。 – ephemient 2010-02-01 03:26:04
不,但您可以使用任何改写。
hasA2 :: [A] -> Bool
hasA2 = any $ \x -> case x of { A2 _ -> True ; _ -> False }
否,原因有二:
对这种表达没有语法支持。
elem
需要一个具体的第一个参数来在作为第二个参数传入的列表中进行搜索(所以你不能通过对语法的一些小修改来完成)。
您可以使用Data.List.find
代替:
import Data.List
isA2 A1 = False
isA2 (A2 _) = True
find isA2 [A1, A2 999]
-- => Just (A2 999)
更新:嗯,迪特里希打我,但我会离开这里了这个答案的替代解决方案(以及在上面的解释,FWIW )。
使用模板的Haskell A液:
{-# LANGUAGE TemplateHaskell #-}
import Data.ADT.Getters
import Data.Maybe
data A = A1 | A2 Integer
$(mkADTGetters ''A)
hasA2 = any (isJust . gA2)
注:Data.ADT.Getters
处于"peakachu" hackage包,暂时。此功能将被添加到"derive",然后从“peakachu”中删除。
要扩大迪特里希的回答是:
如果你只是想匹配一个构造函数的名字,不顾一切领域,您可以使用此模式:A2 {}
。
hasA2 :: [A] -> Bool
hasA2 = any $ \x -> case x of { A2 {} -> True; _ -> False }
此功能将继续,如果你以后决定另一个字段添加到A2
构造工作。
而且,如果你正在使用ephemient Eq
情况下,你也可以把它像这样:
elem (A2 {})
同样,无视所有字段(它们初始化为底部)。
是的,这是可行的!如果你不喜欢模板haskell(在另一个答案中使用),那么你可以使用“DrIFT”或“派生”工具。
{-! global : is !-}
data Foo = A1 | A2 Int deriving (Show, Eq, Ord)
hasA2 :: [Foo] -> Bool
hasA2 = any isA2
即键入和编译器pipleine的一部分运行通过漂移产生的是*函数的模块中的所有的数据类型的源代码:
{-* Generated by DrIFT : Look, but Don't Touch. *-}
isA1 (A1) = True
isA1 _ = False
isA2 (A2 _) = True
isA2 _ = False
或者,也可以使用“派生”。使用上面的代码,删除{ - ! !... - }指令,并插入:
{-!
deriving instance Is Foo
!-}
或者你可以节省一些打字和修改原来的代码如下:
data Foo = A1 | A2 Int deriving (Show, Eq, Ord {-! Is !-})
和 “导出” 将产生:
isA1 :: Foo -> Bool
isA1 (A1{}) = True
isA1 _ = False
isA2 :: Foo -> Bool
isA2 (A2{}) = True
isA2 _ = False
似乎我已经找到了替代解决方案:([z |(A2 z)< - x]/= []) – me2 2010-01-28 09:25:00
如果你想nitpicky你最好使用'null'而不是'/ = []',因为它不需要Ord约束:not $ null [()| A2 _ < - x] – Martijn 2010-01-28 09:44:28