2015-03-27 5 views
1

Так что я не уверен, что то, что я хочу, на самом деле изменчивая переменная, но это что-то похожее на нее.Mutable variable и case statement в Haskell

я принципиально хочу сделать это:

case thing of 
    True -> p <- func 
    False -> p <- otherFunc 
return Record {program=p, otherFields=oF} 

Любой способ, которым я могу сделать что-то подобное? Я сделал свою функцию возвратом записи ввода-вывода, поэтому попробовал просто поместить результат в оператор case, но моя последняя строка должна вернуть его, а это не так.

ответ

6

Вам просто нужно двигаться, где 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} 
+0

Yup! Омг, это здорово, большое спасибо! – Gentatsu

3

Yup!

let p = case thing of 
    ... 
return ... 

Это синтаксис в do нотации (сам синтаксис) для

let p = case thing of 
    ... 
    in do 
     ... 
     return ... 
+0

Удивительный, спасибо! Сначала вы ответили, поэтому я сделаю все правильно! Но только часть! – Gentatsu

+0

@ Gentatsu, наши ответы немного разные! Подумайте, где каждый из них подходит. – dfeuer

+0

По сути, они оба говорят, что вы позволили переменной равняться результату case case, чего я хотел, и ваш заставил меня понять это, поэтому я чувствую, что вы этого заслуживаете. – Gentatsu

 Смежные вопросы

  • Нет связанных вопросов^_^