Newest at the top
| 2026-03-09 10:30:06 +0100 | <merijn> | Good to see that that code hasn't been maintained/updated for, like, 10 GHC releases now >.> |
| 2026-03-09 10:29:23 +0100 | <merijn> | For a non-trivial real world example of the power of just stacking a bunch of monoids, see: https://github.com/haskell/cabal/blob/master/Cabal/src/Distribution/Simple/Program/GHC.hs#L67-L144 |
| 2026-03-09 10:27:55 +0100 | castan | (~castan@2a02:2f0f:8210:d800:1625:20a6:66c:b041) (Quit: castan) |
| 2026-03-09 10:26:42 +0100 | <merijn> | castan: It's even neater since you can my personal favourite "mwhen :: Monoid b => Boolean -> b" to selectively disable parts of aggregation/sorting |
| 2026-03-09 10:25:56 +0100 | <merijn> | It also works well for stuff like aggregating data, since you just need a monoid on the final result and then you can compose any number of functions computing stuff that take the same arguments into bigger aggregations |
| 2026-03-09 10:24:53 +0100 | <merijn> | It's stupid powerful for trivially writing really complicated sorts |
| 2026-03-09 10:24:35 +0100 | <castan> | this is really cool, thank you for the info |
| 2026-03-09 10:24:04 +0100 | <merijn> | but yes |
| 2026-03-09 10:23:56 +0100 | <merijn> | castan: lexicographic order on the whatever functions you pass to it |
| 2026-03-09 10:23:30 +0100 | <castan> | oh and then with <> you get a lexicographic order on the pairs |
| 2026-03-09 10:22:57 +0100 | <merijn> | So "comparing snd <> comparing fst" passes the same 2 tuples to both functions and mappend results, which simply returns the result of "comparing snd" **unless** that returns EQ, then it falls back to the result of "comparing fst" |
| 2026-03-09 10:21:55 +0100 | <merijn> | Ordering is just "data Ordering = LT | EQ | GT" with "mappend LT _ = LT; mappend GT _ = GT; mappend EQ x = x" (i.e. it gives you the left-most non-equal value) |
| 2026-03-09 10:20:12 +0100 | <lambdabot> | Ord a1 => (a2, a1) -> (a2, a1) -> Ordering |
| 2026-03-09 10:20:11 +0100 | <merijn> | :t comparing snd |
| 2026-03-09 10:20:07 +0100 | <lambdabot> | Ord a => (a, b) -> (a, b) -> Ordering |
| 2026-03-09 10:20:06 +0100 | <merijn> | :t comparing fst |
| 2026-03-09 10:19:36 +0100 | <merijn> | castan: But that instance applies recursively (i.e. since "a -> b" is a Monoid when 'b' is, then "c -> a -> b" (which is just "c -> (a -> b)" is also a monoid) |
| 2026-03-09 10:18:48 +0100 | <merijn> | castan: "instance Monoid b => Monoid (a -> b) where mappend f g = \x -> mappend (f x) (g x)" |
| 2026-03-09 10:18:25 +0100 | fp | (~Thunderbi@2001:708:20:1406::1370) fp |
| 2026-03-09 10:18:08 +0100 | <merijn> | castan: Basically the monoid on functions is "if the final result is a monoid, then simply pass each argument to both functions and mappend the result" |
| 2026-03-09 10:18:04 +0100 | fp | (~Thunderbi@staff235.kora-dyn.aalto.fi) (Client Quit) |
| 2026-03-09 10:17:37 +0100 | fp | (~Thunderbi@staff235.kora-dyn.aalto.fi) fp |
| 2026-03-09 10:17:24 +0100 | <merijn> | Even funkier with newtypes like Down :p |
| 2026-03-09 10:17:19 +0100 | <lambdabot> | [(3,1),(2,1),(1,1),(3,9),(2,9),(1,9)] |
| 2026-03-09 10:17:17 +0100 | <merijn> | > sortBy (comparing snd <> comparing (Down . fst)) [(3,9), (2,9), (1, 9), (3, 1), (2, 1), (1,1)] |
| 2026-03-09 10:16:49 +0100 | <merijn> | It's slow as sin |
| 2026-03-09 10:16:46 +0100 | <merijn> | Holy moly is Hackage being DOSed or something? |
| 2026-03-09 10:15:55 +0100 | <castan> | that's wild, I need to play with it for a bit to understand how |
| 2026-03-09 10:15:18 +0100 | <lambdabot> | [(2,1),(1,1),(3,1),(2,9),(1,9),(3,9)] |
| 2026-03-09 10:15:17 +0100 | <probie> | > sortBy (comparing snd <> comparing (flip mod 2 . fst) <> comparing fst) [(3,9), (2,9), (1, 9), (3, 1), (2, 1), (1,1)] |
| 2026-03-09 10:14:12 +0100 | <merijn> | Magic |
| 2026-03-09 10:14:02 +0100 | <lambdabot> | [(1,1),(2,1),(3,1),(1,9),(2,9),(3,9)] |
| 2026-03-09 10:14:00 +0100 | <merijn> | > sortBy (comparing snd <> comparing fst) [(3,9), (2,9), (1, 9), (3, 1), (2, 1), (1,1)] |
| 2026-03-09 10:13:14 +0100 | <lambdabot> | (a -> a -> Ordering) -> [a] -> [a] |
| 2026-03-09 10:13:13 +0100 | <merijn> | :t sortBy |
| 2026-03-09 10:13:08 +0100 | <lambdabot> | Ord a => (b -> a) -> b -> b -> Ordering |
| 2026-03-09 10:13:07 +0100 | <merijn> | :t comparing |
| 2026-03-09 10:12:02 +0100 | <merijn> | castan: And absolutely brilliant use for this monoid is the fact that Ordering is a monoid, so you can use it to combine comparison functions to do multi way ordering |
| 2026-03-09 10:10:58 +0100 | <merijn> | __monty__: Which, if you don't realise the monoid on functions is confusing |
| 2026-03-09 10:10:40 +0100 | <merijn> | __monty__: No, his question is why is it correct at all :p |
| 2026-03-09 10:10:20 +0100 | <merijn> | best monoit instance ever |
| 2026-03-09 10:10:19 +0100 | <__monty__> | Were you expecting a different result? Because `mappend mempty (Sum 3) = Sum 3` too. |
| 2026-03-09 10:08:22 +0100 | <lambdabot> | Num t => Sum t |
| 2026-03-09 10:08:21 +0100 | <mesaoptimizer> | :t mappend mempty Sum 3 |
| 2026-03-09 10:08:15 +0100 | <lambdabot> | Num a => a -> Sum a |
| 2026-03-09 10:08:14 +0100 | <mesaoptimizer> | :t mappend mempty Sum |
| 2026-03-09 10:08:07 +0100 | <lambdabot> | Monoid a => a -> a |
| 2026-03-09 10:08:06 +0100 | <mesaoptimizer> | :t mappend mempty |
| 2026-03-09 10:07:59 +0100 | <lambdabot> | Monoid a => a -> a -> a |
| 2026-03-09 10:07:58 +0100 | <mesaoptimizer> | :t mappend |