Non-injective functions and URL slugs - Haskell

Welcome to the Functional Programming Zulip Chat Archive. You can join the chat here.

Sridhar Ratnakumar

So I began writing this:

-- | Make a non-injective function injective
mkInjective :: [a] -> (a -> b) -> a -> b
mkInjective domain f = undefined
Sridhar Ratnakumar

Final implementation:

-- | Make a non-injective function injective
mkInjective :: Ord b => [a] -> (a -> b) -> a -> (b, Maybe a)
mkInjective domain f =
  let image = map f domain
      nonInjectiveImage = Set.fromList $ dups image
   in \a ->
        let b = f a
         in if Set.member b nonInjectiveImage
              then (b, Just a)
              else (b, Nothing)
    dups = Map.keys . Map.filter (> 1) . Map.fromListWith (+) . fmap (,1 :: Int)

Guess what it is used for.

Sridhar Ratnakumar

Entirely thing has been put in the Web.UniqSlug module:

Zulip Archive viewer (statically generated HTML). Contribute to srid/zulip-archive development by creating an account on GitHub.
Sridhar Ratnakumar

See it in action here. Note that almost all topics have "clean URLs" (matching topic title), except for two topics titled "Interface". They differ only case of the first letter, so their URL slug has a md5 hash appended to it.