2

What is the better way to convert a given Char to lowercase version?

One method could be with converting to String:

charToLower :: Char -> Char
charToLower char =
   Maybe.fromMaybe char 
     $ CodeUnits.charAt 0 
     $ String.toLower 
     $ CodeUnits.singleton char

Is there a more appropriate way in terms of performance/simplicity?

There is also a toLower` from CodePoint.Unicode package but I wonder if it is a preferred way.

WHITECOLOR
  • 24,996
  • 37
  • 121
  • 181
  • https://pursuit.purescript.org/packages/purescript-strings/3.0.0/docs/Data.Char#v:toLower – Robin Zigmond May 16 '21 at 14:42
  • 1
    It is an old version of the package. – WHITECOLOR May 16 '21 at 14:46
  • apologies - you're quite correct. That will teach me for just googling and going with the first thing I found! I'd be very surprised if a basic and fundamental function like `toLower` has been completely removed in a later version but you may be right, I haven't found it so far. – Robin Zigmond May 16 '21 at 14:49
  • 1
    There is one https://pursuit.purescript.org/packages/purescript-unicode/5.0.0/docs/Data.CodePoint.Unicode#v:toLower but I wonder if it is a preferred way. – WHITECOLOR May 16 '21 at 15:59
  • 1
    I'd say yes go with the one from `unicode` – Random Dev May 17 '21 at 05:47
  • Well i'm not sure how it can make things better though, it is really not clear how to go from CodePoints -> Char without converting to Stirng. – WHITECOLOR May 17 '21 at 15:46
  • 1
    Here the thing: lower/uppercase conversion of a char sometimes results in more than one char. https://stackoverflow.com/questions/62769106/unable-to-get-uppercase-to-%C3%9F-german-character-called-eszett That's why the type signatures in purescript-unicode are what they are. – James Brock May 21 '21 at 06:08

1 Answers1

2

I guess the fastest way is just to use FFI. One can easily write toLower this way:

// Foreign/Char.js

module.exports.toLower = function charToLower(c) {
  return c.toLower();
}
-- Foreign/Char.purs
module Foreign.Char where

foreign import toLower :: Char -> Char

Or if you want to express it in purescript only:

import Unsafe.Coerce (unsafeCoerce)
import Data.String as S

toLower :: Char -> Char
toLower = unsafeCoerce >>> S.toLower >>> unsafeCoerce

That eventually boils down to the same js code. You cannot break Char's invariants as it's initially just a subset of String and has the same runtime representation.

aleksxor
  • 7,535
  • 1
  • 22
  • 27
  • This is a valid method, but only if you need performance badly. – WHITECOLOR May 18 '21 at 08:52
  • 1
    Given: 1. an input `Char` value is just a single character `String` limited to unicode's Plane 0 space (justifies first unsafeCoerce) 2. any lowercased character from unicode's Plane 0 lies within the same plane (justifies second unsafeCoerce) The output of this function pretty much fullfills the `Char` requirements and the function itself must be type safe. – aleksxor May 18 '21 at 09:09