gcanti / fp-ts

Functional programming in TypeScript
https://gcanti.github.io/fp-ts/
MIT License
10.85k stars 503 forks source link

Case-insensitive string module #1472

Open mlegenhausen opened 3 years ago

mlegenhausen commented 3 years ago

First of all I would like to validate that my assumption is correct that the set of case-insensitive strings form a total oder? If that holds I would like to contribute a caseInsensitiveOrd (naming suggestions are welcome) instance.

gkamperis commented 3 years ago

do you mean case-insensitive?

mlegenhausen commented 3 years ago

Doh, fixed 😅

gcanti commented 3 years ago

@mlegenhausen what's the definition of compare?

mlegenhausen commented 3 years ago

My naive approach would be the following definition:

import * as O from 'fp-ts/Ord'

declare const Ord: Ord<string>

export const ciOrd: Ord<string> = pipe(Ord, O.contramap(s => s.toLowerCase()))
mlegenhausen commented 3 years ago

Found a haskell package that does even more than I currently thought of: https://hackage.haskell.org/package/case-insensitive-1.2.1.0/docs/Data-CaseInsensitive.html

Maybe the cleaned way would be add a caseInsensitiveString.ts module.

mlegenhausen commented 3 years ago

Based on the ideas from the package I think it would be the cleanest way to use a branded type and copy the functionality from the string module.

import * as E from 'fp-ts/Eq'
import * as M from 'fp-ts/Monoid'
import * as O from 'fp-ts/Ord'
import * as S from 'fp-ts/Semigroup'
import * as Sh from 'fp-ts/Show'
import * as s from 'fp-ts/string'

export type CaseInsensitiveString = string & { readonly CaseInsensitiveString: unique symbol }

export const fromString = (s: string): CaseInsensitiveString => s.toLowerCase() as any

export const Eq: E.Eq<CaseInsensitiveString> = s.Eq

export const Semigroup: S.Semigroup<CaseInsensitiveString> = s.Semigroup as any

export const Monoid: M.Monoid<CaseInsensitiveString> = s.Monoid as any

export const Ord: O.Ord<CaseInsensitiveString> = s.Ord

export const Show: Sh.Show<CaseInsensitiveString> = s.Show

export const empty: CaseInsensitiveString = '' as any

export const isEmpty = (s: CaseInsensitiveString): boolean => s.length === 0

export const size = (s: CaseInsensitiveString): number => s.length

Don't know if this a to specific type for fp-ts?