输入'Just'上的解析错误

时间:2016-04-15 03:16:59

标签: haskell

我有这段代码:

myF :: Maybe Int -> Maybe Int -> (Int, Int)
myF mb1 mb2 =
  let var1 = case mb1 of
    Just x -> x
    Nothing -> 123

  let var2 = case mb2 of
    Just x -> x
    Nothing -> 456

  let var3 = (var1 + var2 ) * 333
  (var2, var3)

它给我一个编译错误"在输入'Just'"上解析错误。如何解决?

2 个答案:

答案 0 :(得分:3)

有两个问题:

  1. letof都会引入块。要正确解析事物,case / of块中的模式必须比let块中的模式缩进更多。
  2. 由于您不在do区块内,因此每个let必须附带in。您只需使用一个in块即可减少所需let的总数。
  3. 结合起来,这可以让你:

    myF :: Maybe Int -> Maybe Int -> (Int, Int)
    myF mb1 mb2 =
      let var1 = case mb1 of
            Just x -> x
            Nothing -> 123
    
          var2 = case mb2 of
            Just x -> x
            Nothing -> 456
    
          var3 = (var1 + var2 ) * 333
      in (var2, var3)
    

答案 1 :(得分:2)

正如丹尼尔所说,let绑定的内容需要比其模式更加缩进。此外,您需要let … in块之外的do。如果你真的想要使用三个let,你最终会得到这样的结果:

myF :: Maybe Int -> Maybe Int -> (Int, Int)
myF mb1 mb2 =
  let var1 = case mb1 of
       Just x  -> x
       Nothing -> 123
  in let var2 = case mb1 of
          Just x  -> x
          Nothing -> 456
     in let var3 = (var1 + var2 ) * 333
        in (var2, var3)

但是,多个let … in通常可以重构为一个let … in。请注意,即使是使用单个let … in的版本也会违反不要重复自己的规则:

myF :: Maybe Int -> Maybe Int -> (Int, Int)
myF mb1 mb2 =
  let var1 = case mb1 of  -- (1)
       Just x  -> x
       Nothing -> 123
      var2 = case mb1 of  -- (2)
       Just x  -> x
       Nothing -> 456
      var3 = (var1 + var2 ) * 333
  in (var2, var3)

您在(1)(2)中两次使用(差不多)相同的代码。此外,您可能错过了(2)中引入的错误,其中我使用了mb1而不是mb2。您可以使用fromMaybe(在Data.Maybe中)使其更具可读性:

import Data.Maybe (fromMaybe)
-- fromMaybe :: a -> Maybe a -> a

myF :: Maybe Int -> Maybe Int -> (Int, Int)
myF mb1 mb2 =
  let var1 = fromMaybe 123 mb1
      var2 = fromMaybe 456 mb2
      var3 = (var1 + var2) * 333
  in (var2, var3)

锻炼

  • 如果不查看其来源,请尝试自己实施fromMaybe
  • 重写myF,这次使用where代替let … in(只是为了更熟悉Haskell的语法)。