Sharlene Roberts
Sharlene Roberts

Reputation: 145

How to implement a placeholder in a string haskell

How can I create a function that would print sentences that have placeholders/variables in the missing spaces and then take user input and print a complete sentence by inserting the values into the placeholders.

I'm trying to print multiple sentences(statements) with missing words which then give the user the option to select 4 choices of various words to complete the sentence. The goal is to have variables added within the missing spaces that acts as placeholders which will then take the user input, and store the value into the variables where words are missing to then print a complete sentence. I have explained this further in the "What I have in mind section"

Eg. This sentence ____ not _____.
Options:
1. Is, complete
2. is, finished
3. etc
4. etc

What I have in mind

I'm trying to achieve something along the lines of using a placeholder for those spaces with no text where I can then assign values in said placeholder after the user selects the choice.

  1. someFunction that prints sentence
    "This sentence is $a not $b."

Where $a and $b and variables/placeholders that I can call later to store the words that the user selects.

  1. someFunction that takes the sentence from the first function and takes the options that are printed from another function, and place the value into the placeholders to make the sentence complete.

What I did

My implementation is done in a way that is just rewriting the entire sentence with each possible option that the user can choose, and then printing the sentence that matches the option that the user chooses. This doesn't give me the functional approach that I am looking for, since it's more or a hard coded approach which can get tedious when using multiple sentences which will then have the 4 options for each sentence.

My Code

   --First Version
import Data.List
import System.IO

main :: IO()

sentences = do
    putStrLn "The Cat is ______ from ______ the city \n"
    putStrLn "Here are your options:"
    putStrLn "A. big, nearby"
    putStrLn "B. Nearby, in"
    putStrLn "C: You, By"
    putStrLn "D: By, Yourself"
    option <- getChar
    if (option == 'A' || option == 'a')
        then putStrLn "The Cat is big from nearby the city"
    else if (option == 'B' || option == 'b')
        then putStrLn "The Cat is nearby from in the city"
    else putStrLn "Error"

main = sentences   

Upvotes: 1

Views: 687

Answers (1)

Pierre Thierry
Pierre Thierry

Reputation: 5129

I like using string-interpolate for this because it's exception-safe. Then you can use Maybe's fold maybe to replace your if:

{-# LANGUAGE QuasiQuotes #-}

module Main where

import Control.Monad (forM_)
import Data.Char (toUpper)
import Data.List (lookup)
import Data.Maybe (maybe)
import Data.String.Interpolate ( i )
import System.IO

sentence :: (String, String) -> String
sentence (word1, word2) = [i|The Cat is #{word1} from #{word2} the city \n|]

type Choice = (Char, (String, String))

choices :: [Choice]
choices = [ ('A', ("big"   , "nearby"))
          , ('B', ("Nearby", "in"))
          , ('C', ("You"   , "By"))
          , ('D', ("By"    , "Yourself"))
          ]

presentChoice :: Choice -> IO ()
presentChoice (option, (word1, word2)) =
    putStrLn [i|#{option}. #{word1}, #{word2}|]

sentences = do
    putStrLn $ sentence ("______", "______")
    putStrLn "Here are your options:"
    forM_ choices presentChoice
    option <- fmap toUpper getChar
    putStrLn $ maybe "Error" sentence $ lookup option choices

main :: IO()
main = sentences

Upvotes: 1

Related Questions