2009-07-21 116 views
9

我有一个非常简单的问题。我想在使用绑定操作符的代码块后面使用where子句,但是出现编译错误。Haskell:我可以使用绑定运算符(>> =)在块之后使用where子句吗?

下面是一个简单的例子:

main = 
    putStrLn "where clause test:" >> 
    return [1..10] >>= \list -> 
    print list' 
     where list' = reverse list -- test1.hs:5:28: Not in scope: `list' 

我可以使用列表中的let子句”作为

main = 
    putStrLn "where clause test:" >> 
    return [1..10] >>= \list -> 
    let list' = reverse list -- works of course 
    in print list' 

,但我真的很喜欢它,如果我可以使用where子句。 ..

我也试图与做记号

main = do 
    putStrLn "where clause test:" 
    list <- return [1..10] 
    print list' 
     where list' = reverse list --test3.hs:5:30: Not in scope: `list' 

同样的问题。在这种情况下我可以使用where子句吗?

回答

10

正如ephemient解释的那样,您不能按照您的方式使用where子句。是因为在此代码

错误:

main = 
    return [1..10] >>= \list -> 
    print list' 
    where 
     list' = reverse list 

where -clause被附接到主函数。

下面是同样的功能与更多的括号:

main = return [1..10] >>= (\list -> print list') 
    where 
    list' = reverse list 

我认为它相当明显为什么你的“out of scope”错误:list结合深得main表情里面,不是在where子句达到。

我通常在这种情况下做了什么(而且我被一堆同样的东西咬了一口)。我只是介绍一个函数,并将list作为参数。

main = do 
    list <- return [1..10] 
    let list' = f list 
    print list' 
    where 
    f list = reverse list -- Consider renaming list, 
          -- or writing in point-free style 

当然,我想在f功能实际代码是一个很大的,只是reverse,这就是代替结合内嵌let你为什么想成为一个where子句中。如果f函数中的代码非常小,我只需将它写入let绑定中,并且不会引入引入新函数的开销。

1

据我所知,where子句只用于本地绑定。 >>(=)绑定语句的内部部分不是本地绑定(该句子中有两种不同的绑定)。

比较本:

main = f [1..10] 

f list = 
    putStrLn "where clause test:" >> print list' 
     where list' = reverse list 

您可能要参考Haskell 98 syntax report - 不知道它会有多大的帮助可以。

如果我错了,有人肯定会纠正我,但我敢肯定你不能在上面显示的样式中使用where子句。 list将永远不会成为where子句的范围,除非它是函数的参数。

+0

lambda抽象是一个表达式,不是声明或绑定,尽管它可以绑定新名字... – ephemient 2009-07-21 04:26:56

+0

哇,谁-1?我认为这是正确的,如果不够完整的话。 – ephemient 2009-07-21 04:27:52

+0

它不相关。 OP想要使用“list”,这是来自一堆monadic计算的结果;不是来自monad外部的值 – newacct 2009-07-21 04:47:36

11

问题是,let-in是一个表达式,它可以在其他表达式中使用,而where只能用于(module | class | instance | GADT | ...)声明或(函数|模式)绑定。

从上declarations and bindings哈斯克尔98报告,

p | g1=e1
    | g2=e2
    …
    | gm=em
  where {decls}

是糖

p= letdeclsin
      ifg1thene1else
      ifg2thene2else
      …
      ifgmthenemelse error "Unmatched pattern"

,或者通过移除警卫简化的东西,

p=ewhere {decls}

是糖

在函数和模式绑定中。即使您的do {&hellip; }构造。

如果你想有一个更大的表达式中结合当地的一个特定的子表达式,则需要使用let - in(或简称let一个do内,但这是let只是糖 - in)。

你甚至不能写

main = do 
    putStrLn "where clause test: " 
    list <- return [1..10] 
    (print list' where list' = reverse list) 

因为 “êwhere {decls}” 是不是合法的表达– where只能在声明和绑定使用。

main = do 
    putStrLn "where clause test: " 
    list <- return [1..10] 
    let list' = list'' where list'' = reverse list 
    print list' 

这是合法的(如果有点人为的话)。

相关问题