8000 Implement Multiple-Choice Reading Option · Issue #81 · chshersh/iris · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Implement Multiple-Choice Reading Option #81
Open
@initial-mockingbird

Description

@initial-mockingbird

A generalization for #9 .

The choices can be modeled as their display name coupled with a parsing function to the desired data type of the answer:

data MultipleChoiceOption a = MultipleChoiceOption
    { displayName   :: ByteString  
    , parsingFun    :: ByteString -> Maybe a 
    }

Then, we can model multiple choices as: a message prompt, a non-empty list of choices (whose default choice will always be the head), and a value for the default option:

data MultipleChoicePrompt a = MultipleChoicePrompt
    { promptMessage :: ByteString  
    , promptOptions :: NonEmpty (MultipleChoiceOption a) 
    , defaultValue  :: a  
    }

Thus, the following prompt data:

MultipleChoicePrompt 
    { promptMessage="Are you sure?"
    , promptOptions=
        MultipleChoiceOption 
            { displayName="y"
            , parsingFun = \s -> if s == "y" then Just Yes else Nothing
            }
        :|
        [ MultipleChoiceOption 
            { displayName="n"
            , parsingFun = \s -> if s == "n" then Just No else Nothing
            }
        ]
    , defaultValue=Yes
    }

Will represent:

Are you sure? [y]/n

Finally, we can define a function that:

  • Prints the question (via an aux function that takes the MultipleChoicePrompt
  • Reads answer
  • Returns the first choice that is parsed correctly (can be done with a foldMap over the Alt monoid)
  • Or prints an error message to stderr in case of error, returning Nothing
multipleChoiceQuestion
    ::  MonadIO m
    => MultipleChoicePrompt a
    -> m (Maybe a)

An example run would be:

>>> multipleChoiceQuestion
    MultipleChoicePrompt 
    { promptMessage="Are you sure?"
    , promptOptions=
        MultipleChoiceOption 
            { displayName="y"
            , parsingFun = \s -> if s == "y" then Just Yes else Nothing
            }
        :|
        [ MultipleChoiceOption 
            { displayName="n"
            , parsingFun = \s -> if s == "n" then Just No else Nothing
            }
        , MultipleChoiceOption 
            { displayName="cancel"
            , parsingFun = \s -> if s == "cancel" then Just Cancel else Nothing
            }
        ]
    , defaultValue=Yes
    }
>>> n
Just No

Something to notice is that the function will take the default value and build a parser to accept empty responses:

>>> multipleChoiceQuestion
    MultipleChoicePrompt 
    { promptMessage="Are you sure?"
    , promptOptions=
        MultipleChoiceOption 
            { displayName="y"
            , parsingFun = \s -> if s == "y" then Just Yes else Nothing
            }
        :|
        [ MultipleChoiceOption 
            { displayName="n"
            , parsingFun = \s -> if s == "n" then Just No else Nothing
            }
         , MultipleChoiceOption 
            { displayName="cancel"
            , parsingFun = \s -> if s == "cancel" then Just Cancel else Nothing
            }
        ]
    , defaultValue=Yes
    }
>>> 
Just Yes

Finally, some points that might need refinement:

  • Default value might be different than the value that is returned by the parsing function.
  • Instead of printing to stderr and returning Nothing, it may be better to return Either Bytestring a and let another function decide what to do.
  • Instead of having a Non-Empty List, we could have either a tuple with the first two options and a normal List for the rest, or a sized container (i.e, something from Data.Size). Having a multiple option question with just one option feels wrong.

I'm willing to try and accommodate all suggestions to this implementation :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0