String literal typing appears to be a common feature of type systems bolted onto dynamic languages:
# Python
MyStringBool = Literal("Yes") | Literal("No")
// TypeScript
type MyStringBool = "Yes" | "No"
I assume it exists to compensate for the previous lack of typing, and consequent likelihood of ersatz typing via strings.It would seem pretty unnecessary in Haskell, where you can just define whatever types you want without involving strings at all:
data MyBool = Yes | No
Of course you'd need a trivial parser, though this is probably a good idea for any string type: parseMyBool :: String -> MyBool
parseMyBool "Yes" = Yes
parseMyBool "No" = No
parseMyBool _ = error "..."
Interestingly, dynamic languages which make use of symbols (Ruby, Elixir, Common Lisp) probably fall closer to Haskell than Python or TS. Elixir example: @type my_bool() :: :yes | :no
@spec parse_my_bool(String.t()) :: my_bool()
def parse_my_bool("Yes"), do: :yes
def parse_my_bool("No"), do: :no
def parse_my_bool(_), do: throw("...")
Where :yes and :no are memory-efficient symbols, not strings.