Недавно я начал использовать вычислительные выражения для упрощения своего кода. Пока что единственным полезным для меня является MaybeBuilder, определенный следующим образом:
type internal MaybeBuilder() =
member this.Bind(x, f) =
match x with
| None -> None
| Some a -> f a
member this.Return(x) =
Some x
member this.ReturnFrom(x) = x
Но я хотел бы изучить другие варианты использования. Одна из возможностей заключается в ситуации, с которой я сейчас сталкиваюсь. У меня есть некоторые данные, предоставленные поставщиком, который определяет симметричную матрицу. Для экономии места дана только треугольная часть матрицы, так как другая сторона просто транспонирована. Итак, если я вижу строку в csv как
азбука, определение, 123
это означает, что значение для строки abc и определения столбца равно 123. Но я не увижу такую строку, как
деф, азбука, 123
потому что эта информация уже дана из-за симметричного характера матрицы.
Я загрузил все эти данные в Map<string,Map<string,float>>
, и у меня есть функция, которая получает значение для любой записи, которая выглядит так:
let myLookupFunction (m:Map<string,Map<string,float>>) s1 s2 =
let try1 =
match m.TryFind s1 with
|Some subMap -> subMap.TryFind s2
|_ -> None
match try1 with
|Some f -> f
|_ ->
let try2 =
match m.TryFind s2 with
|Some subMap -> subMap.TryFind s1
|_ -> None
match try2 with
|Some f -> f
|_ -> failwith (sprintf "Unable to locate a value between %s and %s" s1 s2)
Теперь, когда я знаю о вычислительных выражениях, я подозреваю, что операторы соответствия можно скрыть. Я могу немного почистить его, используя MaybeBuilder, вот так
let myFunction2 (m:Map<string,Map<string,float>>) s1 s2 =
let maybe = new MaybeBuilder()
let try1 = maybe{
let! subMap = m.TryFind s1
return! subMap.TryFind s2
}
match try1 with
|Some f -> f
|_ ->
let try2 = maybe{
let! subMap = m.TryFind s2
return! subMap.TryFind s1
}
match try2 with
|Some f -> f
|_ -> failwith (sprintf "Unable to locate a value between %s and %s" s1 s2)
При этом я перешел от 4 операторов совпадения к 2. Есть ли (не надуманный) способ еще больше очистить это с помощью вычислительных выражений?