在Haskell函数之外的位置使用

在Haskell函数之外的位置使用,haskell,Haskell,我想知道是否可以在函数外使用where? e、 g 很明显,当我编译它时,它不起作用 我只想将x声明为fun的局部变量您的函数的类型错误,无法用作do块中的最终表达式。它需要返回一个Monad m=>m Int值,而不仅仅是Int。由于main(通常使用)必须是IO操作,这意味着m应该是IO fun :: Int -> IO Int fun n = return (n + 1) 不过,在这种情况下,let比where更合适 main = do let x = 30 in

我想知道是否可以在函数外使用where? e、 g

很明显,当我编译它时,它不起作用


我只想将x声明为fun的局部变量

您的函数的类型错误,无法用作
do
块中的最终表达式。它需要返回一个
Monad m=>m Int
值,而不仅仅是
Int
。由于
main
(通常使用)必须是
IO
操作,这意味着
m
应该是
IO

 fun :: Int -> IO Int
 fun n = return (n + 1)    
不过,在这种情况下,
let
where
更合适

main = do
  let x = 30 in fun x
现在,
x
只在调用
fun
的范围内。如果你写

main = do
  let x = 30
  fun x
然后,
x
在技术上属于
do
块的其余部分,而不仅仅是调用
fun
。尽管共享相同的关键字
let
,但
do
块中的
let
与常规
let
表达式之间存在明显差异。(关系是这样的

do
  let name = value
  foo
相当于

let name = value
in do
    foo
)


请注意,
do
本身并不创建一元值;它只是假设一元属性的各种运算符的语法糖。快速概述:

  • do{x>=(\x->foox)
  • do{foo;bar;}
    变成
    foo>>bar
  • do{let x=y;foo;}
    在do-foo中变成
    let x=y
  • dofoo
    变成
    foo

  • 与您的代码最相关的是规则4;
    do
    块中的单个表达式等同于表达式本身,这意味着您可以剥离
    do
    。只有在
    do
    块被删除后,Haskell才开始键入检查结果。

    是否这样做?将OP的代码复制/粘贴到ghci中对我来说很好。我很抱歉我很好奇他报告的错误是什么。啊,好的观点。我修复了OP没有特别指出的另一个错误,那就是
    fun
    使用了错误的类型,因为它在
    do
    块中。这不是
    main::IO()的要求吗
    ?因此编译器也会拒绝使用
    main::IO a
    (除非我记错了什么).
    main
    只是一个可以绑定到任何东西的名称。如果它被用作完整程序的入口点,那么它必须绑定到一个
    IO
    操作才能运行程序。在这里,更一般的monad约束仅仅来自这样一个事实:它绑定到一个由
    do
    块定义的值。啊,好的。不,我认为原因是,
    do
    语法(特别是,
    )或monad(如调用
    return
    )已使用。
    do fun x
    简化为简单的
    fun x
    。这不起作用的唯一原因是类型不匹配。您可以在此上下文中使用
    where
    -阅读错误消息!
    let name = value
    in do
        foo