|
|
|
|
|
by troad
29 days ago
|
|
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. |
|
In TS in particular, in combination with other features (mapped types), they are equivalent to row polymorphism + whatever Haskell/GHC features enable type families to specialize on constant literal arguments (or you can use atomic types, but that's not structural / open-world)... so pretty advanced.
This is valid TS/Python:
The equivalent Haskell requires using several extensions.