这里有三种类似但又不同的定义方式:
你可以在某些定义之后添加where
从句--大多数是类似等式的绑定。因此,你可以在函数结尾、或者在使用了let
或周围的where
从句定义的东西之后加一个where
从句。
另一方面,let x = ... in ...
是一个表达式,它求值为in
之后的部分,该部分是let
之后的内容唯一可见的地方。
在do
块内,因为已经有了一个隐含的作用域嵌套(在定义后的位置才会可见),所以你只需要使用单独的let x = ...
。这实际上与前一种形式是相同的--let
之后的do
块的其余部分就是in ...
部分。
如果你想要一个使用在do
块内已经定义过的东西的局部定义,你唯一的选择就是第三个(或将其他值作为参数传递)。然而,对于像你的示例一样的独立辅助函数,任何形式都可以。这里是你的示例,以演示每个形式:
第一种形式,其中func
在foo
中任何地方都可见,包括在where
从句中定义的任何其他内容:
foo = do ...
mapM_ func aList
...
return aValue
where func x = x + 1
第二种样式,在这种情况下 func
只在 let
表达式内部可见,而该表达式是整个 do
块:
foo = let func x = x + 1
in do
...
mapM_ func aList
...
return aValue
第三种方式是在do
块内部定义。这种情况下,在let
之后才能看到func
;在第一个...中它还没有被定义。
<code>foo = do ...
let func x = x + 1
mapM_ func aList
...
return aValue
</code>
另外,为了保证准确性:由于 let ... in ...
是一个表达式,你也可以在任何需要表达式的地方使用它,来命名一些本地定义。下面是另一个例子:
<code>foo = do ...
let func x = x + 1 in mapM_ func aList
...
return aValue
</code>
与之前一样,func
仅在let
表达式内可见,在此情况下它是其后的单个表达式中可见,而其他地方则不可见。
mapM_
,非常有用。我只担心它会在顶层函数命名空间中污染let
中定义的func
名称(小问题)。 - Ralph