Haskell 如何基于一元模式匹配进行过滤?
我有以下问题: 给定一个类型Haskell 如何基于一元模式匹配进行过滤?,haskell,pattern-matching,filtering,maybe,Haskell,Pattern Matching,Filtering,Maybe,我有以下问题: 给定一个类型data T=T(可能是Int),我如何筛选一个列表以获取非Nothing值 输入 a = [T (Just 3), T Nothing, T (Just 4)] b = [T (Just 3), T (Just 4)] 所需输出 a = [T (Just 3), T Nothing, T (Just 4)] b = [T (Just 3), T (Just 4)] 我试过这样的方法: b = filter (\x-> x@(Just t)) a …
data T=T(可能是Int)
,我如何筛选一个列表以获取非Nothing
值
输入
a = [T (Just 3), T Nothing, T (Just 4)]
b = [T (Just 3), T (Just 4)]
所需输出
a = [T (Just 3), T Nothing, T (Just 4)]
b = [T (Just 3), T (Just 4)]
我试过这样的方法:
b = filter (\x-> x@(Just t)) a
…认为我可以根据模式匹配进行筛选,但我得到了错误:
Pattern syntax in expression context: x@(Just t)
Did you mean to enable TypeApplications?
稍后,您将能够解压缩内部值(仅在
下)并相应地使用它 我认为在这里我们可以更好地使用列表理解的模式匹配语义:
result = [ e | e@(T (Just _)) <- a]
因此,这将不仅“过滤”值,而且同时解包。因此,T Nothing
s被忽略,只有被包装的T(Just e)
s被保留,相应的e
s最终出现在列表中。我认为这里我们可以更好地使用列表理解的模式匹配语义:
result = [ e | e@(T (Just _)) <- a]
因此,这将不仅“过滤”值,而且同时解包。因此,T Nothing
s被忽略,只有包装的T(Just e)
s被保留,相应的e
s在列表中结束。模式匹配只在函数的参数中起作用,而不是在主体中起作用。您需要匹配的模式是T
,使用类似maybe
的反同构将包装值转换为布尔值
Prelude> a = [T (Just 3), T Nothing, T (Just 4)]
Prelude> filter (\(T x) -> maybe False (const True) x) a
[T (Just 3),T (Just 4)]
但是,请注意,maybe False(const True)
已经定义为数据。maybe.isJust
Prelude> import Data.Maybe
Prelude> filter (\(T x) -> isJust x) a
[T (Just 3),T (Just 4)]
如果有一些类型为T->Maybe Int
的函数与isJust
组合,则可以简化谓词。例如:
Prelude> data T = T { getT :: Maybe Int } deriving Show
Prelude> a = [T (Just 3), T Nothing, T (Just 4)]
Prelude> filter (isJust . getT) a
[T {getT = Just 3},T {getT = Just 4}]
模式匹配只适用于函数的参数,而不适用于主体。您需要匹配的模式是T
,使用类似maybe
的反同构将包装值转换为布尔值
Prelude> a = [T (Just 3), T Nothing, T (Just 4)]
Prelude> filter (\(T x) -> maybe False (const True) x) a
[T (Just 3),T (Just 4)]
但是,请注意,maybe False(const True)
已经定义为数据。maybe.isJust
Prelude> import Data.Maybe
Prelude> filter (\(T x) -> isJust x) a
[T (Just 3),T (Just 4)]
如果有一些类型为T->Maybe Int
的函数与isJust
组合,则可以简化谓词。例如:
Prelude> data T = T { getT :: Maybe Int } deriving Show
Prelude> a = [T (Just 3), T Nothing, T (Just 4)]
Prelude> filter (isJust . getT) a
[T {getT = Just 3},T {getT = Just 4}]
如果您想在T
s列表中获得Int
值的列表(如此键入[T]->[Int]
),那么从数据中。也许已经几乎完全满足了您的要求。除此之外,还需要一个类型为T->Maybe Int
import Data.Maybe ( mapMaybe )
data T = T (Maybe Int)
deriving (Eq, Show)
unT :: T -> Maybe Int
unT (T x) = x
filterTs = mapMaybe unT
然后:
在我看来,将此筛选操作的类型设置为[T]->[Int]
比返回包含非无值的T
值更有用;原因是,即使您将a
过滤到[T(仅3),T(仅4)]
,那么稍后处理该问题的代码仍然必须在上进行模式匹配,以获得Int
值,即使您知道永远不会有无
1,因为T
仍然硬编码为不包含任何内容
作为一般规则,如果您正在过滤(或默认或其他)以保证没有一个案例,那么您应该考虑将其转换为不再具有这种情况的类型。它通常使生成的数据更容易处理(例如,不需要模式匹配或
fmap
s进入冗余层),并且有助于避免错误
还有catMaybes::[maybea]->[a]
,它可以“过滤出没有映射的任何内容”,但是由于您映射到unapp,因此T
构造函数mappea
更适合
1和这种“我知道这里永远不会有什么都没有,所以我不必处理它”的情况是一个非常丰富的bug源,当将来隐藏不变的东西发生变化时,很容易被破坏。因此,实际上编写代码来利用什么都没有
“不可能”的知识,这甚至不是一个好主意;你仍然应该处理这两种情况 如果您想在T
s列表中获得Int
值的列表(如此键入[T]->[Int]
),那么从数据中。也许已经几乎完全满足了您的要求。除此之外,还需要一个类型为T->Maybe Int
import Data.Maybe ( mapMaybe )
data T = T (Maybe Int)
deriving (Eq, Show)
unT :: T -> Maybe Int
unT (T x) = x
filterTs = mapMaybe unT
然后:
在我看来,将此筛选操作的类型设置为[T]->[Int]
比返回包含非无值的T
值更有用;原因是,即使您将a
过滤到[T(仅3),T(仅4)]
,那么稍后处理该问题的代码仍然必须在上进行模式匹配,以获得Int
值,即使您知道永远不会有无
1,因为T
仍然硬编码为不包含任何内容
作为一般规则,如果您正在过滤(或默认或其他)以保证没有一个案例,那么您应该考虑将其转换为不再具有这种情况的类型。它通常使生成的数据更容易处理(例如,不需要模式匹配或
fmap
s进入冗余层),并且有助于避免错误
还有catMaybes::[maybea]->[a]
,它可以“过滤出没有映射的任何内容”,但是由于您映射到unapp,因此T
构造函数mappea
更适合
1和这种“我知道这里永远不会有什么都没有,所以我不必处理它”的情况是一个非常丰富的bug源,当将来隐藏不变的东西发生变化时,很容易被破坏。因此,实际上编写代码来利用什么都没有
“不可能”的知识,这甚至不是一个好主意;你仍然应该处理这两种情况 这回答了问题的字母,但我敢打赌,[e|T(只是e)是的,这正是问题的答案