2017-07-25 42 views
7

从一些书,我有下面的代码片段“做”和“哪里”混合?

mutableUpdateIO :: Int -> IO (MV.MVector RealWorld Int) 
mutableUpdateIO n = do 
    mvec <- GM.new (n + 1) 
    go n mvec 
    where 
    go 0 v = return v 
    go n v = (MV.write v n 0) >> go (n - 1) v 

mutableUpdateST :: Int -> V.Vector Int 
mutableUpdateST n = 
    runST $ do 
    mvec <- GM.new (n + 1) 
    go n mvec 
    where 
    go 0 v = V.freeze v 
    go n v = (MV.write v n 0) >> go (n - 1) v 

hindent缩进他们。现在我想介绍所有的大括号和分号,所以空白不再相关。只因为我好奇。

第二个例子表明,where属于整个runST $ do ...表达式,但是第一个例子表明,where不知何故是go n mvec语句的一部分。在Haskell Report Chapter 2.7阅读中,我试图引进括号和分号在第一个例子像

mutableUpdateIO :: Int -> IO (MV.MVector RealWorld Int) 
mutableUpdateIO n = do { 
    mvec <- GM.new (n + 1); 
    go n mvec; 
    where { 
    go 0 v = return v; 
    go n v = (MV.write v n 0) >> go (n - 1) v; 
    } ; } 

但我得到一个解析错误。这是为什么?

为什么布局hindent产生的第一个例子mutableUpdateIO有效的Haskell?不应该在我的上述尝试中引入大括号和分号吗?

+0

'where'与'do' afaik分开。我认为哪里会自动具有功能范围。 – Carcigenicate

+0

关联:https://stackoverflow.com/questions/9721354/in-haskell-what-is-the-scope-of-a-where-clause-when-dealing-with-guards – Carcigenicate

+10

'do ...'是一个表达。 “where”从不附加到表达式,只附加到声明。 – melpomene

回答

9

where块既不属于runST $ do ...表达式也不属于go n mvec语句;它们属于mutableUpdateIO n = ...声明和mutableUpdateST n = ...声明。括号和分号应该是这样的:

mutableUpdateIO :: Int -> IO (MV.MVector RealWorld Int) 
mutableUpdateIO n = do { 
    mvec <- GM.new (n + 1); 
    go n mvec; 
    } where { 
    go 0 v = return v; 
    go n v = (MV.write v n 0) >> go (n - 1) v; 
    } 

从第一章2.7报告非正式说明有关一句话是这样的:

一个右括号也被插入时包含的词类布局列表结束;也就是说,如果在紧密大括号合法的地方遇到非法的词位,则会插入紧密大括号。

由于where是表达内的非法语义,这结束do块和一个靠近支架被插入那里。这也解释了为什么生成的布局合理。