Haskell中的可变变量和case语句

Gen*_*tsu 1 haskell mutable case-statement switch-statement

所以我不确定我想要的是否实际上是一个可变变量,但它与它相似.

我基本上想要这样做:

case thing of
    True -> p <- func
    False -> p <- otherFunc
return Record {program=p, otherFields=oF}
Run Code Online (Sandbox Code Playgroud)

我有什么方法可以做那样的事情?我已经让我的函数返回一个IO记录,所以尝试将返回放在case语句中,但是我的最后一行需要返回它,但事实并非如此.

bhe*_*ilr 6

你只需要移动case发生的地方:

p <- case thing of
        True -> func
        False -> otherFunc
return $ Record {program=p, otherFields=oF}
Run Code Online (Sandbox Code Playgroud)

但是,这是假设func,并otherFunc具有相同类型的,即IO Program,在那里Program是什么类型p的.

你必须这样做,因为语法定义(或多或少)为

case <expr> of
    <pattern1> -> <expr1>
    <pattern2> -> <expr2>
    ...
    <patternN> -> <exprN>
Run Code Online (Sandbox Code Playgroud)

但是,语法<pattern> <- <expr>本身并不是一个表达式,你不能只使用<-语法绑定一个名称来获得一个完整的表达式,之后你必须对它做一些事情.将表达式视为返回值,任何值的东西.该<-语法没有返回值,它是从一元的上下文中提取值,并将其赋值给一个名字.这类似于let x = y没有返回值的方式,它只是将值绑定到名称. xy自己有返回值,但let x = y没有.

这就是为什么你不能只是把p <- func 本身的情况下分支,它必须有其他的事情吧.但是,如果您的整个案例表达式具有类似的返回值IO Program,那么您可以使用它来提取它<-.

几乎所有这些都适用于let绑定.如果你的funcotherFunc函数有类型Program,而不是IO Program,那么你可以做

let p = case thing of
        True -> func
        False -> otherFunc
in Record {program=p, otherFields=oF}
Run Code Online (Sandbox Code Playgroud)

或者更简洁

Record {program=(if thing then func else otherFunc), otherFields=oF}
Run Code Online (Sandbox Code Playgroud)

你也可以使用if-then-elsemonadic bind:

do
    p <- if thing then func else otherFunc
    return $ Record {program=p, otherFields=oF}
Run Code Online (Sandbox Code Playgroud)