Возвращающие различающее объединение в разных состояниях на основе ввода строки в сопоставлении с шаблоном (F #)

#types #f# #pattern-matching #discriminated-union

#типы #f# #сопоставление с шаблоном #дискриминируемое объединение

Вопрос:

 type ColType = I of int | S of string | F of float
  

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

  //create i coltype
    let m (x : int) : ColType =
        ColType.I x
    //create f coltype
    let n (x : float) : ColType = 
        ColType.F x
    //create s coltype
    let b (x : string) : ColType = 
        ColType.S x    

    let pColType =

        let innerFn (charList : char list) = 

            let i = String(List.toArray charList)
            match i with   
            | "int"  -> m
            | "float" ->  n
            | "string" -> b

        many1 parseLowercase |>> innerFn
  

Это все равно выдаст мне ошибку в функции pColType, несмотря на то, что m, n и b возвращают один и тот же тип.

код, такой как parseLowercase и т.д., — это просто код для получения строки, он функционирует как задумано, проблема в том, что возвращаемое значение не является одинаковым, несмотря на то, что все они являются coltype? (несмотря на разные его состояния).

Комментарии:

1. Сейчас у меня нет времени на полный ответ, но тип функции включает все ее входные данные. m , n и b бывают трех разных типов: int -> ColType , float -> ColType и string -> ColType . Итак, ваше match i with выражение возвращает три разных типа, а это недопустимо.

2. Проблема в том, что все ветви a match должны иметь один и тот же тип, и в вашем случае этими ветвями являются m : int -> ColType , n : float -> ColType и b : string -> ColType . Они возвращают один и тот же тип, но они должны иметь один и тот же тип.

Ответ №1:

Как упоминали rmunn и Romanov, ваши 3 функции имеют разный тип. Вы можете заставить их возвращать один тип, например, obj -> ColType используя box amp; unbox :

 let pColType =

    let innerFn (charList : char list) = 
        let i = String(List.toArray charList)
        match i with   
        | "int"    -> unbox >> m
        | "float"  -> unbox >> n
        | "string" -> unbox >> b
        |_-> failwithf "error %A" i

    many1 parseLowercase |>> innerFn
  

Для этого требуется, чтобы вы box ввели значение перед вызовом результирующей функции.
Поскольку вы создаете синтаксический анализатор, имеет смысл вместо этого заставить его возвращать string -> ColType :

 let pColType =

    let innerFn (charList : char list) = 
        let i = String(List.toArray charList)
        match i with   
        | "int"    -> parseInt    >> m
        | "float"  -> parseFloat  >> n
        | "string" -> parseString >> b
        |_-> failwithf "error %A" i

    many1 parseLowercase |>> innerFn