haskell - 返回值的模式匹配

标签 haskell functional-programming pattern-matching tuples

我知道我可以对这样的函数参数使用模式匹配:

fn :: (Integral a) => (a,a) -> (a, a)
fn (x,y) = (y,x)

但是我怎样才能匹配返回值呢?我希望是这样的:

g :: (Integral a) => a -> a
g z = do
  (x, y) = fn (z, z + 5)
  x `mod` y

这会导致语法错误。有没有办法匹配返回值?基本上,我想将返回的元组拆分为两个变量。

最佳答案

do 被用作monads语法糖。但是,您的函数不是 monad。

您可以做的是使用 let-clause,例如:

g :: (Integral a) => a -> a
g z = <b>let (x,y) = fn (z,(z+5)) in</b> x `mod` y

或者一个where-clause:

g :: (Integral a) => a -> a
g z = x `mod` y
    <b>where (x,y) = fn (z,(z+5))</b>

您还可以在 lambda-expression 中定义 模式,例如:

g :: (Integral a) => a -> a
g z = (\<b>(x,y)</b> -> x `mod` y) $ fn (z,(z+5))

按照这些思路,您还可以定义一个辅助函数来进行模式匹配,例如:

g :: (Integral a) => a -> a
g z = <b>h</b> $ fn (z,(z+5))
    where <b>h</b> (x,y) = x `mod` y

如果有多个模式需要以不同方式处理(例如 NothingJust x 用于 Maybe a类型)。

比如说你定义了一个函数:

foo :: Int -> Int -> Maybe Int
foo x y | x > y = Just x
        | otherwise = Nothing

你可以用辅助函数qux定义bar来处理foo的输出,比如:

bar :: Int -> Int -> Int
bar x y = qux $ foo x y
    where qux Nothing = y
          qux (Just z) = z

最后在2元组的情况下,你可以决定不使用模式匹配,而是使用fst::(a,b) -> asnd::(a,b) -> b,比如:

g :: (Integral a) => a -> a
g z = let <b>t</b> = fn (z,(z+5)) in (<b> fst  t</b>) `mod` (<b>snd t</b>)

但这不太优雅,因为这里必须开始考虑 fstsnd 做什么,而且如果没有优化,它可能会导致额外的计算开销。

选择哪一个当然取决于上下文和个人品味。由于这里的模式是唯一的,我会选择 letwhere 模式,但就像法国人说的:“Les goûts et les couleurs ne se discutent过去了。”。

关于haskell - 返回值的模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43412324/

相关文章:

haskell - 描述给定 foldr 函数的前几个评估步骤

scala - Seq[Int]和List[Int]的区别和转换

javascript - 如何在 JS/TS 函数式编程中使用箭头函数作为属性

string - 在惯用的 Swift 中找到两个字符串的公共(public)前缀

swift - 是否可以使用 'if-case' 代替具有逗号分隔列表的开关?

parsing - haskell - 解析/读取 .pdf 文件的内容

serialization - Data.Binary(或 friend ?)是否有模板 Haskell/派生机制

haskell - 在 Haskell 中将整数转换为 double

可选第一个特殊字符的正则表达式

pattern-matching - 尽管案例拆分,但 Idris 无法解决约束