2010-12-07 2 views
2

Мне нравятся выражения вычислений, но я делаю простые ошибки, такие как забывание ключевого слова return или! на выражениях вроде let! и вернуться !, или я просто забыл написать do !. Это происходит очень часто с государственными монадами, где я, как правило, забываю о состоянии и просто фокусируюсь на монадических операторах, которые я определил.Как лучше поймать недостающую, пусть !, сделать !, вернуться и вернуться! в выражениях вычислений в F #

Я иногда убеждаюсь, что мои монадические операторы возвращают тип «монадного типа» вместо «анонимной» функции. Это помогает отслеживать мою забывчивую типизацию, но на самом деле не идеальна. У кого-нибудь лучшие трюки?

+1

Инкапсуляция состояние внутри типа монады (вместо прохождения вокруг простых функций) является стандартной практикой, отчасти потому, что она позволяет избежать такого рода ошибки. Что вам не нравится в этом подходе? –

+0

Вы правы, я сказал «не идеально», но, возможно, нет другого способа сделать вещи неявно неправильными как можно скорее. Я думаю, что я «вроде», как «голая» функциональная подпись государственной монады. Но обертывание это нормально. Благодарю. – user519985

ответ

3

Учитывая типичную монаду, ваш код не должен компилироваться, если вам не хватает ! после ключевого слова, потому что типы не будут работать. Например:

let sum = async { 
    let x = async { return 1 } 
    let y = async { return 2 } 
    return x + y 
} 

Это не будет компилироваться, потому что вы пытаетесь добавить две Async<int> с, но она будет собирать, если вы измените let с до let! с.

Точно так же, чтобы выявить недостающие return с, просто обратите внимание на предупреждения компилятора сообщений и нечетных монадических типов:

let sum = async { 
    let! x = async { return 1 } 
    let! y = async { return 2 } 
    x + y // warning FS0020 
} 

В этом случае sum является Async<unit>, которое должно быть очевидным, когда вы пытаетесь использовать его в другом месте вашего кода. Кроме того, вы можете использовать аннотацию типа, чтобы сразу поймать эту проблему:

let sum : Async<int> = async { // error FS0001: type mismatch 
    let! x = async { return 1 } 
    let! y = async { return 2 } 
    x + y // warning FS0020 
} 
+0

Правильные, пропуски приводят к ошибкам компилятора. Но с такими кодами, как монодичный синтаксический анализатор, ошибка не всегда явно привязана к ommision. Например, забыв! по возвращении !, возвращается хорошо, но не то, что вы хотите. – user519985

+1

@ user519985 - добавление аннотации типа должно захватывать случаи, когда вы используете 'return' вместо' return! '. – kvb