返回值的模式匹配

jus*_*.me 2 haskell functional-programming tuples pattern-matching

我知道我可以使用模式匹配功能参数,如下所示:

fn :: (Integral a) => (a,a) -> (a, a)
fn (x,y) = (y,x)
Run Code Online (Sandbox Code Playgroud)

但是如何匹配返回值?我希望这样的事情:

g :: (Integral a) => a -> a
g z = do
  (x, y) = fn (z, z + 5)
  x `mod` y
Run Code Online (Sandbox Code Playgroud)

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

Wil*_*sem 8

do使用语法糖单子.但是你的功能不是monad.

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

g :: (Integral a) => a -> a
g z = let (x,y) = fn (z,(z+5)) in x `mod` y
Run Code Online (Sandbox Code Playgroud)

where-clause:

g :: (Integral a) => a -> a
g z = x `mod` y
    where (x,y) = fn (z,(z+5))
Run Code Online (Sandbox Code Playgroud)

您还可以lambda表达式中定义模式,如:

g :: (Integral a) => a -> a
g z = (\(x,y) -> x `mod` y) $ fn (z,(z+5))
Run Code Online (Sandbox Code Playgroud)

沿着这些方向,您还可以定义一个辅助函数来执行模式匹配,例如:

g :: (Integral a) => a -> a
g z = h $ fn (z,(z+5))
    where h (x,y) = x `mod` y
Run Code Online (Sandbox Code Playgroud)

如果有需要进行不同的处理(如几种模式这可能是有用的Nothing,并Just xMaybe a类型).

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

foo :: Int -> Int -> Maybe Int
foo x y | x > y = Just x
        | otherwise = Nothing
Run Code Online (Sandbox Code Playgroud)

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

bar :: Int -> Int -> Int
bar x y = qux $ foo x y
    where qux Nothing = y
          qux (Just z) = z
Run Code Online (Sandbox Code Playgroud)

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

g :: (Integral a) => a -> a
g z = let t = fn (z,(z+5)) in ( fst  t) `mod` (snd t)
Run Code Online (Sandbox Code Playgroud)

但这不太优雅,因为这里必须开始思考什么fstsnd做什么,如果不进行优化,它可能会导致额外的计算开销.

选择哪一个当然取决于背景和个人品味.由于这里的模式是唯一的,我会选择letwhere模式,但像法国人所说:" Lesgoûtsetles couleurs ne se discutent pas. ".

  • @Lazersmoke不,在该代码中没有使用`Monad`.只需手动运行[desugaring rules](https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-470003.14),您就会发现不需要. (4认同)