submitted 11 months ago* (last edited 11 months ago) by to c/programmer_humor@programming.dev
 

top 50 comments

sorted by: hot top controversial new old
[–] 103 points 11 months ago (17 children)

You gotta admit though, Haskell is crazy good for parsing and marshaling data

  • source
  • hideshow 17 child comments
  • [–] 43 points 11 months ago (11 children)

    Yes. I'm divided into "hum... 100 lines is larger than I expected" and "what did he mean 'from scratch'? did he write the parser combinators? if so, 100 lines is crazy small!"

    But I'm settling in believing 80 of those lines are verbose type declarations.

  • source
  • parent
  • hideshow 11 child comments
  • [–] 18 points 11 months ago* (last edited 11 months ago) (4 children)

    I decided to write it myself for fun. I decided that "From Scratch" means:

    • No parser libraries (parsec/happy/etc)
    • No using read from Prelude
    • No hacky meta-parsing

    Here is what I came up with (using my favourite parsing method: parser combinators):

    import Control.Monad ((>=>), replicateM)
    import Control.Applicative (Alternative (..), asum, optional)
    import Data.Maybe (fromMaybe)
    import Data.Functor (($>))
    import Data.List (singleton)
    import Data.Map (Map, fromList)
    import Data.Bifunctor (first, second)
    import Data.Char (toLower, chr)
    
    newtype Parser i o = Parser { parse :: i -> Maybe (i, o) } deriving (Functor)
    
    instance Applicative (Parser i) where
      pure a = Parser $ \i -> Just (i, a)
      a <*> b = Parser $ parse a >=> \(i, f) -> second f <$> parse b i
    instance Alternative (Parser i) where
      empty = Parser $ const Nothing
      a <|> b = Parser $ \i -> parse a i <|> parse b i
    instance Monad (Parser i) where
      a >>= f = Parser $ parse a >=> \(i, b) -> parse (f b) i
    instance Semigroup o => Semigroup (Parser i o) where
      a <> b = (<>) <$> a <*> b
    instance Monoid o => Monoid (Parser i o) where
      mempty = pure mempty
    
    type SParser = Parser String
    
    charIf :: (a -> Bool) -> Parser [a] a
    charIf cond = Parser $ \i -> case i of
      (x:xs) | cond x -> Just (xs, x)
      _ -> Nothing
    
    char :: Eq a => a -> Parser [a] a
    char c = charIf (== c)
    
    one :: Parser i a -> Parser i [a]
    one = fmap singleton
    
    str :: Eq a => [a] -> Parser [a] [a]
    str = mapM char
    
    sepBy :: Parser i a -> Parser i b -> Parser i [a]
    sepBy a b = (one a <> many (b *> a)) <|> mempty
    
    data Decimal = Decimal { mantissa :: Integer, exponent :: Int } deriving Show
    
    data JSON = Object (Map String JSON) | Array [JSON] | Bool Bool | Number Decimal | String String | Null deriving Show
    
    whitespace :: SParser String
    whitespace = many $ asum $ map char [' ', '\t', '\r', '\n']
    
    digit :: Int -> SParser Int
    digit base = asum $ take base [asum [char c, char (toLower c)] $> n | (c, n) <- zip (['0'..'9'] <> ['A'..'Z']) [0..]]
    
    collectDigits :: Int -> [Int] -> Integer
    collectDigits base = foldl (\acc x -> acc * fromIntegral base + fromIntegral x) 0
    
    unsignedInteger :: SParser Integer
    unsignedInteger = collectDigits 10 <$> some (digit 10)
    
    integer :: SParser Integer
    integer = asum [char '-' $> (-1), char '+' $> 1, str "" $> 1] >>= \sign -> (sign *) <$> unsignedInteger
    
    -- This is the ceil of the log10 and also very inefficient
    log10 :: Integer -> Int
    log10 n
      | n < 1 = 0
      | otherwise = 1 + log10 (n `div` 10)
    
    jsonNumber :: SParser Decimal
    jsonNumber = do
      whole <- integer
      fraction <- fromMaybe 0 <$> optional (str "." *> unsignedInteger)
      e <- fromIntegral . fromMaybe 0 <$> optional ((str "E" <|> str "e") *> integer)
      pure $ Decimal (whole * 10^log10 fraction + signum whole * fraction) (e - log10 fraction)
    
    escapeChar :: SParser Char
    escapeChar = char '\\'
      *> asum [
        str "'" $> '\'',
        str "\"" $> '"',
        str "\\" $> '\\',
        str "n" $> '\n',
        str "r" $> '\r',
        str "t" $> '\t',
        str "b" $> '\b',
        str "f" $> '\f',
        str "u" *> (chr . fromIntegral . collectDigits 16 <$> replicateM 4 (digit 16))
      ]
    
    jsonString :: SParser String
    jsonString =
      char '"'
      *> many (asum [charIf (\c -> c /= '"' && c /= '\\'), escapeChar])
      <* char '"'
    
    jsonObjectPair :: SParser (String, JSON)
    jsonObjectPair = (,) <$> (whitespace *> jsonString <* whitespace <* char ':') <*> json
    
    json :: SParser JSON
    json =
      whitespace *>
        asum [
          Object <$> fromList <$> (char '{' *> jsonObjectPair `sepBy` char ',' <* char '}'),
          Array <$> (char '[' *> json `sepBy` char ',' <* char ']'),
          Bool <$> asum [str "true" $> True, str "false" $> False],
          Number <$> jsonNumber,
          String <$> jsonString,
          Null <$ str "null"
        ]
        <* whitespace
    
    main :: IO ()
    main = interact $ show . parse json
    
    

    This parses numbers as my own weird Decimal type, in order to preserve all information (converting to Double is lossy). I didn't bother implementing any methods on the Decimal, because there are other libraries that do that and we're just writing a parser.

    It's also slow as hell but hey, that's naive implementations for you!

    It ended up being 113 lines. I think I could reduce it a bit more if I was willing to sacrifice readability and/or just inline things instead of implementing stdlib typeclasses.

  • source
  • parent
  • hideshow 4 child comments
  • load more comments (3 replies)
  • load more comments (5 replies)
    [–] 84 points 11 months ago (8 children)

    Jokes on her, I've transitioned since last Christmas.

  • source
  • hideshow 8 child comments
  • [–] 80 points 11 months ago (1 child)

    Who needs a girl when you have monads to keep you warm?

  • source
  • hideshow 1 child comment
  • [–] 63 points 11 months ago* (last edited 11 months ago) (1 child)

    No mom, I'm gonna BE a girl for Christmas. puts on programming socks

  • source
  • hideshow 1 child comment
  • load more comments (1 reply)
    [–] 39 points 11 months ago (2 children)

    You just need to find a girl that also likes Tsoding! Then, you can ask her "Hey, do you have plans for Christmas? I'd love it if we could do AoC (Advent of Code) in a language we both hate!"

  • source
  • hideshow 2 child comments
  • [+] 37 points 11 months ago* (last edited 4 months ago) (2 children)
  • [–] 36 points 11 months ago (23 children)

    There are far more male programmers... As a programmer, be gay or stay alone... Choose!

  • source
  • hideshow 23 child comments
  • [–] 30 points 11 months ago (7 children)

    Oh that explains why my wife is gay

  • source
  • parent
  • hideshow 7 child comments
  • [–] 9 points 11 months ago (3 children)

    She sleeps with men, that's pretty gay

  • source
  • parent
  • hideshow 3 child comments
  • load more comments (1 reply)
  • load more comments (1 reply)
  • [–] 25 points 11 months ago (6 children)

    Can programmers only be with other programmers or am I missing something?

  • source
  • parent
  • hideshow 6 child comments
  • load more comments (1 reply)
  • [–] [S] 17 points 11 months ago (5 children)

    There are those who transition, so a significant chunk of that male programmer population is "male" as in quotation marks, only that some transition earlier than others. Does not guarantee that you can get the transgender autistic puppygirl (or other variations) of your dreams, since many of them are lesbians.

    But also feel free to look outside your field for a partner. It's okay to date an artist as a programmer.

  • source
  • parent
  • hideshow 5 child comments
  • [–] 9 points 11 months ago (3 children)

    I think programmer should be seen as a gender itself.

    I'm currently transitioning myself, already have a homeserver and a Linux PC, can't wait to be a real programmer.

  • source
  • parent
  • hideshow 3 child comments
  • load more comments (1 reply)
  • load more comments (1 reply)
    [–] 28 points 11 months ago (7 children)
  • [–] 8 points 11 months ago (4 children)

    not sure if it's sarcastic: point of view

  • source
  • parent
  • hideshow 4 child comments
  • [+] 24 points 11 months ago* (last edited 7 months ago)
    [removed by mod]
  • source
  • [–] 23 points 11 months ago (2 children)

    NOTE: no proper error reporting

    Add those few lines, will ya?

  • source
  • hideshow 2 child comments
  • [–] 18 points 11 months ago (3 children)
  • [–] 17 points 11 months ago

    I wouldn't trust a guy letting their battery go that low either

  • source
  • [–] 13 points 11 months ago (1 child)

    I'm a girl. I'm not interested in Haskell, that's too frigging endofunctiorific. Erlang! That's what all the cool guys are doing.

  • source
  • hideshow 1 child comment
  • load more comments (1 reply)
    [–] 12 points 11 months ago (4 children)

    A JSON parser in Haskell, what a day to have eyes

  • source
  • hideshow 4 child comments
  • load more comments (4 replies)
    [–] 10 points 11 months ago*

    He won't be done debugging her by then. She'll be ready for beta testing next year.

  • source
  • [–] 9 points 11 months ago

    Hello everyone, and welcome to yet another recreational programming session with who?

  • source
  • load more comments
    view more: next ›