Utils.purs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. module Browser.Utils
  2. ( UnregisteredListener
  3. , UnregisteredListener2
  4. , UnregisteredListener3
  5. , Listener
  6. , Listener2
  7. , Listener3
  8. , mkListenerUnit
  9. , mkListenerOne
  10. , mkListenerTwo
  11. , mkListenerThree
  12. , unwrapForeign
  13. , unsafeLog
  14. , unsafeLog'
  15. , eqBy
  16. , sortByKeyIndex
  17. ) where
  18. import Control.Alt (map)
  19. import Control.Alternative (pure)
  20. import Control.Monad.Except (runExcept)
  21. import Data.Array as A
  22. import Data.Either (Either(..))
  23. import Data.Eq (class Eq, (==))
  24. import Data.Foldable (fold)
  25. import Data.Function (($))
  26. import Data.Generic.Rep (class Generic)
  27. import Data.Ord (class Ord)
  28. import Data.Tuple as T
  29. import Effect (Effect)
  30. import Effect.Exception (throw)
  31. import Foreign (Foreign, renderForeignError)
  32. import Foreign.Generic (class GenericDecode, defaultOptions, genericDecode)
  33. import Prelude (Unit, comparing, (>>>))
  34. type UnregisteredListener a
  35. = (a -> Effect Unit)
  36. type UnregisteredListener2 a b
  37. = (a -> b -> Effect Unit)
  38. type UnregisteredListener3 a b c
  39. = (a -> b -> c -> Effect Unit)
  40. newtype Listener a
  41. = Listener (UnregisteredListener a)
  42. newtype Listener2 a b
  43. = Listener2 (UnregisteredListener2 a b)
  44. newtype Listener3 a b c
  45. = Listener3 (UnregisteredListener3 a b c)
  46. foreign import mkListenerUnit :: (Effect Unit) -> Effect (Listener Unit)
  47. foreign import mkListenerOne :: forall a. (UnregisteredListener a) -> Effect (Listener a)
  48. foreign import mkListenerTwo :: forall a b. (UnregisteredListener2 a b) -> Effect (Listener2 a b)
  49. foreign import mkListenerThree :: forall a b c. (UnregisteredListener3 a b c) -> Effect (Listener3 a b c)
  50. unwrapForeign :: forall a rep. Generic a rep => GenericDecode rep => Foreign -> Effect a
  51. unwrapForeign d = case runExcept
  52. $ genericDecode (defaultOptions { unwrapSingleConstructors = true }) d of
  53. Left err -> throw $ A.intercalate ", " (map renderForeignError err)
  54. Right val -> pure val
  55. foreign import unsafeLog' :: forall a. a
  56. foreign import unsafeLog :: forall a. a -> Effect Unit
  57. -- | Given a mapping function from a to b, where Eq is defined for b, return a
  58. -- | comparison function.
  59. eqBy :: forall a b. Eq b => (a -> b) -> (a -> a -> Boolean)
  60. eqBy f = \a b -> f a == f b
  61. -- | Given a mapping function from a to b where Ord is defined for b, sort the
  62. -- | array by the mapping function, tie-breaking using the index.
  63. sortByKeyIndex :: forall a b. Ord b => (a -> b) -> Array a -> Array a
  64. sortByKeyIndex cmp = A.mapWithIndex T.Tuple >>> A.sortBy compareKey >>> map T.snd
  65. where compareGiven = comparing (T.snd >>> cmp)
  66. compareIdx = comparing T.fst
  67. compareKey = fold [compareGiven, compareIdx]