И вот, благодаря паттерн матчингу, их можно объединить:
let sendToStream (str: NetworkStream) (bin: Object) = match bin with | :? string as strn -> str.Write(System.Text.Encoding.UTF8.GetBytes(strn), 0, strn.Length) | :? (byte[]) as bytarr -> str.Write(bytarr, 0, bytarr.Length)
Вот такая вот функция. Что радует - увеличившийся уровень абстракции - стоит появиться какому-нибудь новому типу, для которого нужен свой способ отправки - все, что нужно изменить - паттерн. Благодаря наличию Object на верхнем уровне мы можем совать какие угодно данные в функцию. Правда, тут стоит следить за наследованием - ведь проверка типов может не дойти до нашего "нового" типа. Поэтому наиболее частные типы следует размещать как можно раньше.
P.S. Кстати, в приведенном примере компилятор найдет изъян - не покрыты все паттерны. Дело лечится добавлением граничного случая
| _ -> failwith "Invalid input"
например.
Могу обобщить: в большинстве языков семейства ML (SML, OCaml, F#) сравнение с образцом вообще на высоте.
ОтветитьУдалитьТолько Haskell подкачал - у него pattern matching неисчерпывающий (non-exhaustive), то-есть в твоем случае предупреждения от компилятора о непокрытых паттернах ты-б не дождался.
Duck typing какой-то. В F# и прочих ML есть более правильный для этого механизм, который точно так же будет применим и здесь, но при этом будет сохранять строгую типизацию.
ОтветитьУдалитьЧем вам discriminated union не гож?
type Data = StringData of string | BinaryData of byte[]
И паттерн матчинг без приведения типов сработает, и добавление новых типов данных не так уж сложно, да и за наследованием следить не надо.