Haskell 如何跨模式匹配执行where子句
我可以得到一个Haskell 如何跨模式匹配执行where子句,haskell,Haskell,我可以得到一个where子句来跨模式工作,该子句与case语句匹配: updateHung :: Text -> Maybe Char -> Int updateHung word got = let x = case got of Just l | elem l . unpack $ word -> pass | otherwise -> strike
where
子句来跨模式工作,该子句与case
语句匹配:
updateHung :: Text -> Maybe Char -> Int
updateHung word got =
let x = case got of
Just l
| elem l . unpack $ word -> pass
| otherwise -> strike
Nothing -> pass
where
strike = 1
pass = 0
in x
但当我尝试使用多部分函数做同样的事情时,它不起作用:
updateHung :: Text -> Maybe Char -> Int
updateHung word (Just l)
| elem l . unpack $ word = pass
| otherwise = strike
updateHung word Nothing = pass
where
strike = 1
pass = 0
有什么方法可以让它工作吗?在工作版本中,您的
where
子句缩进错误。您将其缩进,就像它附加到case
语句中一样,但实际上它附加到x
的定义中,并且缩进得更清楚
updateHung :: Text -> Maybe Char -> Int
updateHung word got =
let x = case got of
Just l
| elem l . unpack $ word -> pass
| otherwise -> strike
Nothing -> pass
where
strike = 1
pass = 0
in x
where
子句的作用域始终为单个模式,跨越该模式的所有保护。这非常重要,因为这允许它使用模式引入的变量。例如,在pass
的定义中使用l
可能很有用,但如果您可以将其范围限定到整个case
语句,则这将毫无意义
如果希望所有模式的范围内都有变量,则必须在开始模式匹配之前绑定这些变量。使用let
或where
为函数定义一个等式,并在其中定义变量,然后在情况下对所有参数的元组或您关心的参数执行其余逻辑:
updateHung :: a -> Maybe Char -> Int
updateHung word got =
let strike = 1
pass = 0
in case got of
Just l
| elem l . unpack $ word -> pass
| otherwise -> strike
Nothing -> pass
或
解释如何以及为什么将where
子句的范围限定为单个等式,而不是整个定义,并使用case
提供替代方法。但是,为了回答更狭义的问题,如果您想继续使用等式样式,但在where
子句中也有共享的局部定义,您可以使用作用域为相同where
块的局部“worker”函数作为辅助定义,因此它们都在范围内:
updateHung = go
where
go word (Just l)
| elem l $ unpack word = pass
| otherwise = strike
go word Nothing = pass
strike = 1
pass = 0
然后,作为简化,您可以将word
参数提升到updateHung
,因为它在go
中总是以相同的方式匹配:
updateHung word = go
where
go (Just l)
| elem l $ unpack word = pass
| otherwise = strike
go Nothing = pass
strike = 1
pass = 0
当局部定义是递归的,而外部定义只是设置其初始参数时,这通常称为,这在两个方面有利于性能:
共享像word
这样的参数,这些参数在整个内部计算过程中保持不变,而不是重复地将它们作为参数传递给递归调用
允许外部定义内联以暴露更多优化(因为GHC通常不会内联递归函数)
updateHung word = go
where
go (Just l)
| elem l $ unpack word = pass
| otherwise = strike
go Nothing = pass
strike = 1
pass = 0