847
submitted 1 month ago* (last edited 1 month ago) by ZILtoid1991@lemmy.world to c/programmer_humor@programming.dev
top 50 comments
sorted by: hot top controversial new old
[-] balsoft@lemmy.ml 99 points 1 month ago

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

[-] marcos@lemmy.world 43 points 1 month ago

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.

[-] balsoft@lemmy.ml 22 points 1 month ago

You could probably write a very basic parser combinator library, enough to parse JSON, in 100 lines of Haskell

[-] someacnt@sh.itjust.works 10 points 1 month ago

Judging by the Parser newtype, he did.

[-] balsoft@lemmy.ml 15 points 1 month ago* (last edited 1 month ago)

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.

[-] join@lemmy.ml 9 points 1 month ago

With recursive list comprehensions you can cram quite some complexity into one line of code.

load more comments (2 replies)
load more comments (5 replies)
[-] magic_smoke 87 points 1 month ago

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

[-] Fisherswamp@programming.dev 82 points 1 month ago

You can still bring a girl though

load more comments (2 replies)
[-] chellomere@lemmy.world 63 points 1 month ago

I am the girl! Hmm, but maybe I'll bring another one too? 🤔

[-] bhamlin@lemmy.world 14 points 1 month ago
load more comments (3 replies)
[-] CanadaPlus@lemmy.sdf.org 79 points 1 month ago

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

[-] boonhet@sopuli.xyz 21 points 1 month ago

Or become a girl with gonads

[-] tiramichu@sh.itjust.works 61 points 1 month ago* (last edited 1 month ago)

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

[-] Quibblekrust@thelemmy.club 5 points 1 month ago

That's 100% how I read it at first.

[-] yetAnotherUser@lemmy.ca 39 points 1 month ago

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!"

[-] Gumbyyy@lemmy.world 10 points 1 month ago

Well shit, I've never seen AoC before - I'm not usually very interested in programming just for fun, but I might give that a try!

[-] lemmydividebyzero@reddthat.com 35 points 1 month ago

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

[-] captainlezbian@lemmy.world 31 points 1 month ago

Oh that explains why my wife is gay

[-] mathemachristian 12 points 1 month ago

If she was around the same cs students as me then yeah

load more comments (1 replies)
[-] Agent641@lemmy.world 8 points 1 month ago

She sleeps with men, that's pretty gay

[-] captainlezbian@lemmy.world 30 points 1 month ago

There are a lot of things she does but that aint one of them

[-] MrScottyTay@sh.itjust.works 8 points 1 month ago* (last edited 1 month ago)

Think you forgot to check their username before commenting that haha

load more comments (1 replies)
load more comments (1 replies)
[-] undefined@lemmy.hogru.ch 23 points 1 month ago

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

[-] davidagain@lemmy.world 22 points 1 month ago

"JSON parser 100% from scratch in Haskell in 110 lines" doesn't get you horny? I guess some people are just wired differently.

load more comments (3 replies)
[-] lemmydividebyzero@reddthat.com 11 points 1 month ago

But you kind of have to leave the house for that... I mean... We talk about programmers....

/s

load more comments (1 replies)
[-] ZILtoid1991@lemmy.world 18 points 1 month ago

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.

[-] rucksack@feddit.org 9 points 1 month ago

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.

[-] lessthanluigi@lemmy.sdf.org 8 points 1 month ago

I detransitioned from being a programmer and all I have is depression since, maybe I should retransission into being a programmer

[-] shoki@lemmy.world 7 points 1 month ago

and gender confirmation would not be getting called sir/ma'am at the starbucks but people asking you for IT help?

load more comments (1 replies)
load more comments (1 replies)
[-] daniskarma@lemmy.dbzer0.com 11 points 1 month ago

It's not gay if I'm wearing programming socks.

load more comments (1 replies)
[-] Cevilia 35 points 1 month ago

This kind of text hits differently when you're a lesbian.

[-] ILikeBoobies@lemmy.ca 14 points 1 month ago* (last edited 1 month ago)

Wouldn’t it hit the same as it would a straight male?

[-] buddascrayon@lemmy.world 18 points 1 month ago

POV: Not all moms are accepting of their daughters being into girls.

[-] RedSnt@feddit.dk 27 points 1 month ago
[-] whyNotSquirrel@sh.itjust.works 8 points 1 month ago

not sure if it's sarcastic: point of view

[-] AugustWest@lemmy.world 12 points 1 month ago

Title is edited

[-] RedSnt@feddit.dk 6 points 1 month ago

I did consider taking a screenshot before the edit from POW to POV, but eh.

load more comments (2 replies)
[-] MonkderVierte@lemmy.zip 23 points 1 month ago

NOTE: no proper error reporting

Add those few lines, will ya?

[-] ZILtoid1991@lemmy.world 10 points 1 month ago

But that would break the 111 line rule.

load more comments (1 replies)
[-] FiskFisk33@startrek.website 17 points 1 month ago

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

[-] smiletolerantly@awful.systems 17 points 1 month ago
[-] ZILtoid1991@lemmy.world 7 points 1 month ago

There was no ESL moment in Ba Sing Se!

load more comments (2 replies)
[-] gigachad@piefed.social 13 points 1 month ago

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

load more comments (4 replies)
[-] umbraroze@slrpnk.net 12 points 1 month ago

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.

load more comments (1 replies)
[-] bestelbus22@lemmy.world 8 points 1 month ago

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

[-] edinbruh@feddit.it 7 points 1 month ago

If you are writing a parser in haskell just use Happy and get it over with

load more comments (1 replies)
[-] mudkip@lemdro.id 5 points 1 month ago

Well, JSON is an easy format to parse. The spec can fit onto one page.

load more comments
view more: next ›
this post was submitted on 22 Oct 2025
847 points (100.0% liked)

Programmer Humor

27599 readers
3072 users here now

Welcome to Programmer Humor!

This is a place where you can post jokes, memes, humor, etc. related to programming!

For sharing awful code theres also Programming Horror.

Rules

founded 2 years ago
MODERATORS