我有这段代码:
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'"上解析错误。如何解决?
答案 0 :(得分:3)
有两个问题:
let
和of
都会引入块。要正确解析事物,case
/ of
块中的模式必须比let
块中的模式缩进更多。do
区块内,因此每个let
必须附带in
。您只需使用一个in
块即可减少所需let
的总数。结合起来,这可以让你:
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的语法)。