Как создавать состояния в F#

#f#

#f#

Вопрос:

F # новичок здесь. Я сказал новичок? Это мой второй день с F #)

Я хочу создать только два состояния для записи: действительное и недействительное; Я бы хотел сделать недопустимое состояние непредставимым.

Вот мой код:

 module Foo =
    type Success = Success of string
    type Pending = Pending of string
    type Failure = Failure of string

    type Valid = Valid of string
    type InValid = InValid of string

    type StateGranted = { Status: Valid; Msg: Success }
    type StateDenied = { Status: InValid; Msg: Failure }

    type State =
        | StateGranted
        | StateDenied

    let status = Valid "Valid"
    let msg = Success "Success"

    let state = { Status = status; Msg = msg } // I have an error here

    printfn "result %A" state
  

Итак, как я могу создать запись типа State ?
Если пользователь хочет создать

 let state = { Status = Valid; Msg = Pending } // compiler should throw an error here
  

У меня есть фон машинописи

PS Я нашел очень полезную статью, но я ее пока не понимаю

Ответ №1:

Я бы предложил заняться проектом в F #, где ясно, чего вы хотите достичь. Вам нужно прояснить для себя, что такое юридические данные.

  1. Неясно, что Success представляет тип. Является Success "Invalid" ли это законным? Это относится ко всем первым пяти типам, и их можно удалить.

  2. Когда вы пытаетесь определить state , вы, вероятно, предполагаете, что как StateGranted, так и StateDenied являются допустимыми возможностями. Но они не одного типа. Вам нужно определить один тип, который представляет то, что state может быть.

Это сводит ваш код к чему-то вроде:

 [<RequireQualifiedAccess>]
type State =
    | Granted // possibly you mean for there to be string-like data here
    | Denied
    // or possibly there are string functions of it like
    //member t.ValidityString =
    //    match t with
    //    | Granted -> "Valid"
    //    | Denied -> "Denied"
  

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

1. Спасибо, ваш ответ также очень хорош. Мне просто нужно переключить свой разум с машинописного текста на систему типов F #)

2. Да, я согласен с этим. Вам нужно унифицировать тип и, возможно, переосмыслить весь подход. Затем вы можете решить это либо с помощью сопоставления с образцом, либо с помощью активных шаблонов, если это необходимо.

Ответ №2:

У вас ошибка, потому что вывод типа не может различать две записи разных типов, но с одинаковыми свойствами. Вам нужно указать префикс одного из членов:

let state = { StateGranted.Status = status; Msg = msg }