这里有三种相似(但不同)的定义方式:
您可以在某些定义之后附加where子句——主要是方程式样式的绑定。因此,您可以将一个放在函数的末尾,或者在使用let或周围where子句定义的内容之后。
另一方面,let x = ... in ...是一个表达式,其计算结果为 after 部分in,这是后面的东西唯一let可见的地方。
在一个do块内,因为已经有一个隐式嵌套的范围(事物在它们第一次定义后可见),你可以let x = ...单独使用。这实际上与之前的形式相同——do之后的块的其余部分let实际上是in ...部分。
如果您想要一个使用do块中定义的内容的本地定义,您唯一的选择是第三个(或将其他值作为参数传递)。但是,对于像您的示例这样的独立辅助函数,任何样式都可以使用。这是您的示例,以演示每个示例:
第一种样式, where 在func中的任何地方可见,包括子句foo中定义的任何其他内容:where
foo = do ...
mapM_ func aList
...
return aValue
where func x = x + 1
第二种样式, wherefunc仅在let表达式内部可见,在本例中是整个do块:
foo = let func x = x + 1
in do
...
mapM_ func aList
...
return aValue
第三种样式,在do块内定义。在这种情况下,func仅在let;之后可见 首先...它还没有被定义。
foo = do ...
let func x = x + 1
mapM_ func aList
...
return aValue
哦,还有一个好处:既然let ... in ...是一个表达式,你也可以在任何你有表达式的地方使用它,来命名一些本地定义。所以这是另一个例子:
foo = do ...
let func x = x + 1 in mapM_ func aList
...
return aValue
和以前一样,func仅在let表达式内部可见,在这种情况下,它是它之后的单个表达式,在其他任何地方都看不到。