There is a fantastic article by Matt Giuca about mistakes programming language designers make and made with regards to Unicode support (or lack thereof): The importance of language-level abstract Unicode strings.

He notes that only Haskell gets it right. (Maybe Rust got it right since then?)

Winter gets it right as well - strings are treated as sequences of Unicode chars, not sequences of bytes. The encoding (UTF-8) is a hidden implementation detail.

Some example Winter code snippets:

codePoint(elem("a\u{393}c", 0)))   #  returns (int)'a'.
codePoint(elem("a\u{393}c", 1)))   #  returns 0x393.
codePoint(elem("a\u{393}c", 2)))   #  returns (int)'c'.

Note that \u{393} in the above is a Unicode escape sequence specifying the Unicode character U+393.

Edit: Reddit discussion.