Hacker News new | ask | show | jobs
by throwaway183839 4117 days ago
> It feels a little redundant to have to manually list out all the elements when the information is known statically, and updating the list will be necessary if the Peg type changes. In Racket, writing a macro for this would be trivial, but alas, this is Haskell. Perhaps there is a way, I’m just not aware of it.

A reasonably clean way would be to define

  data Color = Red | Green | Blue | Yellow | Orange | Purple
    deriving (Enum, Bounded, Show)
and then (e.g. in ghci) you can do

  >> [minBound .. maxBound] :: [Color]
  [Red,Green,Blue,Yellow,Orange,Purple]
I often define the useful function

  enumerate :: (Enum a, Bounded a) => [a]
  enumerate = [minBound .. maxBound]
for exactly this purpose.
1 comments

Yep, I posted this on r/haskell and someone pointed this out, which is cool. The provided type for Peg didn't derive Enum or Bounded, but it's a good trick to know.
I'm kind of surprised that `enumerate` isn't defined in any standard libraries (as far as I know) since I need it pretty often.

After a while spent programming in Haskell you would probably develop your own mini-library of functions that make your life easier. Another one I often find useful is

  (.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
  (.:) f g = \x y -> f (g x y)
which e.g. allows you to define the absolute distance function

  dist :: (Num a) => a -> a -> a
  dist = abs .: (-)
A fun challenge is figuring out why the definition of (.:) is equivalent to

  (.:) = fmap . fmap

!
> A fun challenge is figuring out why the definition of (.:) is equivalent to

> (.:) = fmap . fmap

> !

Of course it's not really equivalent, since the most general type of the LHS is as you have said, whereas that of the RHS involves functor constraints; but inlining the definition of `fmap` for arrows gives the amusing definition:

    (.:) = (.) . (.)
I tend to figure this sort of thing out by successive eta conversion:

    \f g x y -> f (g x y)
    \f g x y -> (f . g x) y
    \f g x   -> f . g x
    \f g x   -> ((f .) . g) x
    \f g     -> (f .) . g
    \f g     -> ((f .) .) g
    \f       -> ((f .) .)
    \f       -> (.) (f .)
    \f       -> (.) ((.) f)
    \f       -> ((.) . (.)) f
                (.) . (.)
Is there a better way?
Seems like a better name for it would be

  (...) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
since

  (...) = (.) . (.)

.

    (.:) f g = (f .) . g
This can interestingly be generalized(in a way) to get

    (.::) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> d
    (.::) f g = ((f .) .) . g
and so on.

Since fmap = (.), substitution would get your point free form.

The downside of using (.:) is that it is used heavily in other libraries (Aeson for instance) in a very different context (field accessors, similar in look to json's `:`).