Вам просто нужно двигаться, где case
происходит:
p <- case thing of
True -> func
False -> otherFunc
return $ Record {program=p, otherFields=oF}
Но это при условии, что func
и otherFunc
имеют такой же тип, а именно IO Program
, где Program
является любой тип p
есть.
Вы должны сделать это таким образом, потому что синтаксис определяется (более или менее), как
case <expr> of
<pattern1> -> <expr1>
<pattern2> -> <expr2>
...
<patternN> -> <exprN>
Однако синтаксис <pattern> <- <expr>
не само по себе выражение, вы не можете просто связать имя с помощью синтаксис <-
, чтобы получить полное выражение, вам нужно что-то с ним делать потом. Думайте о выражениях как о чем-то, что возвращает значение, любое значение вообще. Синтаксис <-
не имеет возвращаемого значения, он извлекает значение из монадического контекста и присваивает ему имя. Это похоже на то, как let x = y
не имеет возвращаемого значения, это просто привязывает значение к имени. x
и y
сами имеют возвращаемые значения, но let x = y
нет.
Вот почему вы не можете просто поставить p <- func
сам по себе в ветке дела, ему придется иметь с ним другие вещи. Однако если ваш общий случай выражение имеет возвращаемое значение, например IO Program
, вы можете извлечь его с помощью <-
.
Практически все это относится к let
креплениям. Если вместо того, чтобы ваши func
и otherFunc
функции имеют тип Program
, вместо IO Program
, то вы можете просто сделать
let p = case thing of
True -> func
False -> otherFunc
in Record {program=p, otherFields=oF}
или более сжато
Record {program=(if thing then func else otherFunc), otherFields=oF}
Вы можете использовать if-then-else
с монадической связывают, а также:
do
p <- if thing then func else otherFunc
return $ Record {program=p, otherFields=oF}
Yup! Омг, это здорово, большое спасибо! – Gentatsu