2013-05-23 5 views
0

Я продолжаю изучать соответствие шаблону F # с моей простой функцией, которая должна возвращать квадратный корень, если аргументом является число, аргумент в противном случае. Я немного изменил его, и он выглядит следующим образом.Функция F # возвращает несколько типов (возвращает тип общего типа объекта)?

let my_sqrt (o: obj) = 
    match o with 
    | :? float as d -> (sqrt d).ToString() 
    | _ as x -> x.ToString() 

Он отлично работает для моей цели, но что, если я не хочу бросать возвращаемое значение в строку? Как я могу вернуть «какой-то объект», а затем использовать его в printfn "%A" (my_sqrt [| 1; 2; 3 |])?

+3

Если я могу спросить, какова цель возвращения аргумента неизменным, если это не поплавок? В какой ситуации это будет полезно? – sepp2k

+0

Только что написал пример функции, которая возвращает разные типы, чтобы показать, что я хочу знать :-) – asdf

ответ

5

Я думаю, что вы хотите

let my_sqrt (o: obj) = 
    match o with 
    | :? float as d -> (sqrt d) :> obj 
    | _ as x -> x 

только вентиляционный объекта

-1

Я думаю, что ваша функция нормально. Если вы хотите, чтобы вычислить каждый квадратный корень, вы должны сопоставить функции над массивом, как это:

Array.map my_sqrt [| 1.0; 2.0; 3.0 |] |> printfn "%A" 
8

Несмотря на то, что ваш пример просто демонстрация того, что вы пытаетесь сделать, это стоит отметить, что это, вероятно, не очень хороший дизайн. В F #, вы обычно не использовать функции, которые работают на объектах с использованием слепков - лучший способом, чтобы представить это были бы предвзято союз:

type MyInput = 
    | Numeric of float 
    | Other of obj 

let my_sqrt = function 
    | Numeric d -> Numeric (sqrt d) 
    | Other o -> Other o 

Этой функция работает на типе, который является либо Numeric или Other, но благодаря в DU вам не нужно кастинг. Я думаю, что что-то в этом направлении будет лучшим подходом к вашей реальной проблеме.

+0

Можете ли вы объяснить немного больше? Я новичок в F # и сильных типах в целом, так что это выглядит немного запутанным для меня. Мы определяем тип набора типов, определяем функцию, которая работает с ее подтипами, но какая цель при обертке возвращает значения этой функции? Чтобы показать, что функция получает MyInput и возвращает MyInput? – asdf

+1

@dig Идея состоит в том, что вы должны четко указывать, что возвращает функция - если у вас есть функция 'obj -> obj', вы говорите, что она может что-то взять и что-то вернуть. Цель «MyInput» состоит в том, чтобы сказать, что функция принимает «float» (в этом случае она делает что-то особенное) или что-то еще.Я обернул возвращаемое значение в том же типе, потому что я подозревал, что вы захотите провести различие между этими двумя случаями после вызова функции. –

+0

@dig Но я думаю, что трудно дать полезный ответ, не зная больше о конкретном использовании, которое вас интересует. –

0

Как упоминалось в ответе TP, общая идея должна быть, когда это возможно, для получения информации о поверхности вашей системы типов.

  • Именно тогда легче для вас читать и рассуждать вашу программу, так как у вас есть названные вещи.

  • Это означает, что F # может на самом деле работа для вас и сказать вам, когда вы сделали что-то неправильно

Это делает его всегда стоит инвестиций.

0

Я согласен с Томасом в том, что использование Дискриминационного Союза было бы лучше. Там нет либо монад, встроенные в F #, но вы можете использовать Выбор союз, чтобы стандартизировать интерфейс:

let my_sqrt (o : obj) = 
    match o with 
    | :? float as d -> Choice1Of2 (sqrt d) 
    | o -> Choice2Of2 o;; 
Смежные вопросы