commit 3948d4af32b5457222845ba8c4b3741a85ff2b74 Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri Nov 1 06:48:41 2024 +0000 Deploy to GitHub pages diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..4f7e6a8 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +blog.youwen.dev diff --git a/atom.xml b/atom.xml new file mode 100644 index 0000000..f074d30 --- /dev/null +++ b/atom.xml @@ -0,0 +1,122 @@ + + + gradient ascent + + + https://blog.youwen.dev/atom.xml + + Youwen Wu + youwenw@gmail.com + + 2024-05-25T12:00:00Z + + why I made my blog in haskell + + https://blog.youwen.dev/why-i-made-my-blog-in-haskell.html + 2024-05-25T00:00:00Z + 2024-05-25T12:00:00Z + +
+

+ why I made my blog in haskell +

+

+ a purely functional...blog? +

+
2024-05-25
+
+ (last updated: 2024-05-25T12:00:00Z) +
+
+

Welcome! This is the first post on gradient ascent and also one that tests all +of the features.

+

gradient ascent

+

I’ll be writing about computers, code, math, video games, and whatever else +here.

+
+

A monad is just a monoid in the category of endofunctors, what’s the problem?

+
+

haskell?

+

This entire blog is generated with hakyll. It’s +a library for generating static sites for Haskell, a purely functional +programming language. It’s a library because it doesn’t come with as many +batteries included as tools like Hugo or Astro. You set up most of the site +yourself by calling the library from Haskell.

+

Here’s a brief excerpt:

+
main :: IO ()
+main = hakyllWith config $ do
+    forM_
+        [ "CNAME"
+        , "favicon.ico"
+        , "robots.txt"
+        , "_config.yml"
+        , "images/*"
+        , "out/*"
+        , "fonts/*"
+        ]
+        $ \f -> match f $ do
+            route idRoute
+            compile copyFileCompiler
+

The code highlighting is also generated by hakyll.

+
+

why?

+

Haskell is a purely functional language with no mutable state. Its syntax +actually makes it pretty elegant for declaring routes and “rendering” pipelines.

+

I originally wanted to build this entire blog myself. I had a working version +with the Svelte framework, complete with GFM rendering, table of contents, KaTeX +math, code highlighting, static generation, and other goodies. However, it +seemed like a little too much work to maintain. I switched to hakyll because

+
    +
  1. Haskell is cool.
  2. +
  3. It comes with enough features that I don’t feel like I have to build +everything from scratch.
  4. +
  5. It comes with Pandoc, a Haskell library for converting between markdown +formats. It’s probably more powerful than anything you could do in nodejs. +It renders all of the markdown to HTML as well as the math. +
      +
    1. It supports KaTeX as well as MathML. I’m a little disappointed with the +KaTeX though. It doesn’t directly render it, but simply injects the KaTeX +files and renders it client-side.
    2. +
  6. +
+

speaking of math

+

We can have math inline, like so: +ex2dx=π\int_\infty^\infty \, e^{-x^2}\,dx = \sqrt{\pi}. This site ships semantic +MathML math with its HTML, and the MathJax script to the client.

+

It’d be nice if MathML could just be used and supported across all browsers, but +unfortunately we still aren’t quite there yet. Firefox is the only one where +everything looks 80% of the way to LaTeX. On Safari and Chrome, even simple +equations like π\sqrt{\pi} render improperly.

+

Pros of MathML:

+
    +
  • A little more accessible
  • +
  • Can be rendered without additional stylesheets. I just installed the Latin +Modern font, but this isn’t even really necessary
  • +
  • Built-in to most browsers (#UseThePlatform)
  • +
+

Cons:

+
    +
  • Isn’t fully standardized. Might look different on different browsers
  • +
  • Rendering quality isn’t as good as KaTeX
  • +
+

This site has MathJax render all of the math so it looks nice and standardized +across browsers, but the math still displays regardless (like say if MathJax +couldn’t load due to slow network) because of MathML. Best of both worlds.

+

Let’s try it now. Here’s a simple theorem:

+

an+bncn{a,b,c}n3 +a^n + b^n \ne c^n \, \forall\,\left\{ a,\,b,\,c \right\} \in \mathbb{Z} \land n \ge 3 +

+

The proof is trivial and will be left as an exercise to the reader.

+

seems a little overengineered

+

Probably is. Not as much as the old one, though.

+ +]]>
+
+ +
diff --git a/css/code.css b/css/code.css new file mode 100644 index 0000000..9745de8 --- /dev/null +++ b/css/code.css @@ -0,0 +1 @@ +pre>code.sourceCode{white-space:pre;position:relative}pre>code.sourceCode>span{line-height:1.25}pre>code.sourceCode>span:empty{height:1.2em}.sourceCode{overflow:visible}code.sourceCode>span{color:inherit;text-decoration:inherit}div.sourceCode{margin:1em 0}pre.sourceCode{margin:0}@media screen{div.sourceCode{overflow:auto}}@media print{pre>code.sourceCode{white-space:pre-wrap}pre>code.sourceCode>span{text-indent:-5em;padding-left:5em}}pre.numberSource code{counter-reset:source-line 0}pre.numberSource code>span{position:relative;left:-4em;counter-increment:source-line}pre.numberSource code>span>a:first-child::before{content:counter(source-line);position:relative;left:-1em;text-align:right;vertical-align:baseline;border:none;display:inline-block;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:0 4px;width:4em;background-color:#232629;color:#7a7c7d}pre.numberSource{margin-left:3em;border-left:1px solid #7a7c7d;padding-left:4px}div.sourceCode{color:#cfcfc2;background-color:#232629}@media screen{pre>code.sourceCode>span>a:first-child::before{text-decoration:underline}}code span{color:#cfcfc2}code span.al{color:#95da4c;background-color:#4d1f24;font-weight:bold}code span.an{color:#3f8058}code span.at{color:#2980b9}code span.bn{color:#f67400}code span.bu{color:#7f8c8d}code span.cf{color:#fdbc4b;font-weight:bold}code span.ch{color:#3daee9}code span.cn{color:#27aeae;font-weight:bold}code span.co{color:#7a7c7d}code span.cv{color:#7f8c8d}code span.do{color:#a43340}code span.dt{color:#2980b9}code span.dv{color:#f67400}code span.er{color:#da4453;text-decoration:underline}code span.ex{color:#0099ff;font-weight:bold}code span.fl{color:#f67400}code span.fu{color:#8e44ad}code span.im{color:#27ae60}code span.in{color:#c45b00}code span.kw{color:#cfcfc2;font-weight:bold}code span.op{color:#cfcfc2}code span.ot{color:#27ae60}code span.pp{color:#27ae60}code span.re{color:#2980b9;background-color:#153042}code span.sc{color:#3daee9}code span.ss{color:#da4453}code span.st{color:#f44f4f}code span.va{color:#27aeae}code span.vs{color:#da4453}code span.wa{color:#da4453} \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..2096d33 Binary files /dev/null and b/favicon.ico differ diff --git a/images/gradient-ascent.jpg b/images/gradient-ascent.jpg new file mode 100644 index 0000000..b52db7f Binary files /dev/null and b/images/gradient-ascent.jpg differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..c5d7e11 --- /dev/null +++ b/index.html @@ -0,0 +1,200 @@ + + + + youwen wu | gradient ascent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

+ Gradient Ascent. +

+
+
+

+ a web-log about computers, math, hacks, and all the rest. +

+ by Youwen Wu + | + + | + +
+
+
+

Latest

+
+ +
+
+ + + + + diff --git a/out/bundle.css b/out/bundle.css new file mode 100644 index 0000000..9220fe4 --- /dev/null +++ b/out/bundle.css @@ -0,0 +1 @@ +@import url("https://fonts.googleapis.com/css2?family=Merriweather:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400;1,700;1,900&display=swap");@import url("https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap");*,::before,::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x:;--tw-pan-y:;--tw-pinch-zoom:;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position:;--tw-gradient-via-position:;--tw-gradient-to-position:;--tw-ordinal:;--tw-slashed-zero:;--tw-numeric-figure:;--tw-numeric-spacing:;--tw-numeric-fraction:;--tw-ring-inset:;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246/0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur:;--tw-brightness:;--tw-contrast:;--tw-grayscale:;--tw-hue-rotate:;--tw-invert:;--tw-saturate:;--tw-sepia:;--tw-drop-shadow:;--tw-backdrop-blur:;--tw-backdrop-brightness:;--tw-backdrop-contrast:;--tw-backdrop-grayscale:;--tw-backdrop-hue-rotate:;--tw-backdrop-invert:;--tw-backdrop-opacity:;--tw-backdrop-saturate:;--tw-backdrop-sepia:;--tw-contain-size:;--tw-contain-layout:;--tw-contain-paint:;--tw-contain-style:}::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x:;--tw-pan-y:;--tw-pinch-zoom:;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position:;--tw-gradient-via-position:;--tw-gradient-to-position:;--tw-ordinal:;--tw-slashed-zero:;--tw-numeric-figure:;--tw-numeric-spacing:;--tw-numeric-fraction:;--tw-ring-inset:;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246/0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur:;--tw-brightness:;--tw-contrast:;--tw-grayscale:;--tw-hue-rotate:;--tw-invert:;--tw-saturate:;--tw-sepia:;--tw-drop-shadow:;--tw-backdrop-blur:;--tw-backdrop-brightness:;--tw-backdrop-contrast:;--tw-backdrop-grayscale:;--tw-backdrop-hue-rotate:;--tw-backdrop-invert:;--tw-backdrop-opacity:;--tw-backdrop-saturate:;--tw-backdrop-sepia:;--tw-contain-size:;--tw-contain-layout:;--tw-contain-paint:;--tw-contain-style:}/* ! tailwindcss v3.4.14 | MIT License | https://tailwindcss.com */*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::before,::after{--tw-content:''}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Open Sans,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type='button']),input:where([type='reset']),input:where([type='submit']){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type='search']{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder, textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role="button"]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden="until-found"])){display:none}body{--tw-bg-opacity:1;background-color:rgb(214 211 209/var(--tw-bg-opacity));font-family:Merriweather,serif;--tw-text-opacity:1;color:rgb(68 64 60/var(--tw-text-opacity))}body:where(.dark,.dark *){--tw-bg-opacity:1;background-color:rgb(16 16 23/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(231 229 228/var(--tw-text-opacity))}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:0.25rem;margin-bottom:0.25rem}.mb-1{margin-bottom:0.25rem}.mb-14{margin-bottom:3.5rem}.mb-3{margin-bottom:0.75rem}.mb-4{margin-bottom:1rem}.ml-2{margin-left:0.5rem}.mt-1{margin-top:0.25rem}.mt-14{margin-top:3.5rem}.mt-2{margin-top:0.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.inline-flex{display:inline-flex}.h-0\.5{height:0.125rem}.h-1{height:0.25rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:42rem}.max-w-\[200px\]{max-width:200px}.max-w-sm{max-width:24rem}.flex-shrink{flex-shrink:1}.flex-grow{flex-grow:1}.items-center{align-items:center}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.text-nowrap{text-wrap:nowrap}.rounded-lg{border-radius:0.5rem}.rounded-md{border-radius:0.375rem}.rounded-sm{border-radius:0.125rem}.rounded-xl{border-radius:0.75rem}.border-0{border-width:0px}.bg-accent-light{--tw-bg-opacity:1;background-color:rgb(120 113 108/var(--tw-bg-opacity))}.bg-muted-light{--tw-bg-opacity:1;background-color:rgb(168 162 158/var(--tw-bg-opacity))}.p-1{padding:0.25rem}.p-2{padding:0.5rem}.px-1{padding-left:0.25rem;padding-right:0.25rem}.px-2{padding-left:0.5rem;padding-right:0.5rem}.px-4{padding-left:1rem;padding-right:1rem}.pb-12{padding-bottom:3rem}.font-sans{font-family:Open Sans,sans-serif}.font-serif{font-family:Merriweather,serif}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:0.875rem;line-height:1.25rem}.font-light{font-weight:300}.font-medium{font-weight:500}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.tracking-wide{letter-spacing:0.025em}.text-accent-light{--tw-text-opacity:1;color:rgb(120 113 108/var(--tw-text-opacity))}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}.duration-500{transition-duration:500ms}.duration-\[2s\]{transition-duration:2s}.external-link{position:relative;border-radius:0.125rem;padding-right:0.75rem;--tw-text-opacity:1;color:rgb(79 70 229/var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:300ms}.external-link:hover{--tw-bg-opacity:1;background-color:rgb(199 210 254/var(--tw-bg-opacity))}.external-link:where(.dark,.dark *){--tw-text-opacity:1;color:rgb(139 92 246/var(--tw-text-opacity))}.external-link:hover:where(.dark,.dark *){--tw-bg-opacity:1;background-color:rgb(46 16 101/var(--tw-bg-opacity))}.external-link::after{position:absolute;top:0.25rem;right:6px;height:0.5rem;width:0.5rem;--tw-translate-x:50%;--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-radius:9999px;border-width:2px;--tw-border-opacity:1;border-color:rgb(79 70 229/var(--tw-border-opacity))}.external-link:where(.dark,.dark *)::after{--tw-border-opacity:1;border-color:rgb(124 58 237/var(--tw-border-opacity))}.external-link::after{content:""}.post{h1{font-size:1.5rem;line-height:2rem}h1{font-weight:700}h2{position:relative}h2{margin-top:2rem}h2{width:-moz-fit-content;width:fit-content}h2{font-size:1.5rem;line-height:2rem}h2{font-weight:500}h2::after{position:absolute}h2::after{left:0px}h2::after{margin-top:0.5rem}h2::after{display:block}h2::after{height:0.25rem}h2::after{width:3rem}h2::after{border-radius:0.125rem}h2::after{--tw-bg-opacity:1;background-color:rgb(168 162 158/var(--tw-bg-opacity))}h2:where(.dark,.dark *)::after{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity))}h2::after{content:""}h3,h4,h5,h6{margin-top:2rem}h3,h4,h5,h6{font-size:1.25rem;line-height:1.75rem}h3,h4,h5,h6{font-weight:500}h3,h4,h5,h6{--tw-text-opacity:1;color:rgb(120 113 108/var(--tw-text-opacity))}h3:where(.dark,.dark *),h4:where(.dark,.dark *),h5:where(.dark,.dark *),h6:where(.dark,.dark *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}p{margin-top:1rem;margin-bottom:1rem}p{overflow-x:auto}p{font-weight:300}p{line-height:2}@media (min-width:640px){p{font-size:1.125rem;line-height:1.75rem}}@media (min-width:640px){p{line-height:2}}img{margin-left:auto;margin-right:auto}img{margin-top:1.5rem;margin-bottom:1.5rem}img{border-radius:0.5rem}div.sourceCode{border-radius:0.5rem}div.sourceCode{padding:1rem}ol,ul{list-style-position:inside}ol,ul{font-weight:300}ol,ul{line-height:2}@media (min-width:640px){ol,ul{font-size:1.125rem;line-height:1.75rem}}@media (min-width:640px){ol,ul{line-height:2}}ul{list-style-type:disc}ol{list-style-type:decimal}ol ol{margin-left:1rem}ol ol{list-style-type:disc}ol ol ol{margin-left:1rem}ol ol ol{list-style-type:"-"}li{margin-top:0.25rem;margin-bottom:0.25rem}hr{margin-top:2.5rem;margin-bottom:2.5rem}hr{margin-left:auto;margin-right:auto}hr{height:0.5rem}hr{max-width:3rem}hr{border-radius:0.75rem}hr{border-width:0px}hr{--tw-bg-opacity:1;background-color:rgb(168 162 158/var(--tw-bg-opacity))}hr:where(.dark,.dark *){--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity))}blockquote{margin-top:1rem;margin-bottom:1rem}blockquote{height:-moz-fit-content;height:fit-content}blockquote{border-left-width:4px}blockquote{--tw-border-opacity:1;border-color:rgb(120 113 108/var(--tw-border-opacity))}blockquote{padding-left:1rem;padding-right:1rem}blockquote{padding-top:0.125rem;padding-bottom:0.125rem}blockquote{font-style:italic}blockquote{--tw-text-opacity:1;color:rgb(120 113 108/var(--tw-text-opacity))}blockquote:where(.dark,.dark *){--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}blockquote:where(.dark,.dark *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}blockquote>p{margin:0px}a:not(code a){position:relative}a:not(code a){border-radius:0.125rem}a:not(code a){padding-right:0.75rem}a:not(code a){--tw-text-opacity:1;color:rgb(79 70 229/var(--tw-text-opacity))}a:not(code a){transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}a:not(code a){transition-duration:300ms}a:not(code a):hover{--tw-bg-opacity:1;background-color:rgb(199 210 254/var(--tw-bg-opacity))}a:not(code a):where(.dark,.dark *){--tw-text-opacity:1;color:rgb(139 92 246/var(--tw-text-opacity))}a:not(code a):hover:where(.dark,.dark *){--tw-bg-opacity:1;background-color:rgb(46 16 101/var(--tw-bg-opacity))}a:not(code a)::after{position:absolute}a:not(code a)::after{top:0.25rem}a:not(code a)::after{right:6px}a:not(code a)::after{height:0.5rem}a:not(code a)::after{width:0.5rem}a:not(code a)::after{--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}a:not(code a)::after{--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}a:not(code a)::after{border-radius:9999px}a:not(code a)::after{border-width:2px}a:not(code a)::after{--tw-border-opacity:1;border-color:rgb(79 70 229/var(--tw-border-opacity))}a:not(code a):where(.dark,.dark *)::after{--tw-border-opacity:1;border-color:rgb(124 58 237/var(--tw-border-opacity))}a:not(code a)::after{content:""}figure{margin-top:0.5rem;margin-bottom:0.5rem}figure{display:inline-block}figure img{margin-bottom:0.5rem}figure img{vertical-align:top}figure figcaption{text-align:center}details{margin-top:1rem;margin-bottom:1rem}details{overflow-x:auto}details{font-weight:300}details{line-height:2}@media (min-width:640px){details{font-size:1.125rem;line-height:1.75rem}}@media (min-width:640px){details{line-height:2}}details summary{margin-bottom:0.25rem}details summary{cursor:pointer}}.hover\:bg-indigo-200:hover{--tw-bg-opacity:1;background-color:rgb(199 210 254/var(--tw-bg-opacity))}.hover\:text-muted-light:hover{--tw-text-opacity:1;color:rgb(168 162 158/var(--tw-text-opacity))}.group:hover .group-hover\:max-w-\[250px\]{max-width:250px}.group:hover .group-hover\:bg-secondary-light{--tw-bg-opacity:1;background-color:rgb(67 56 202/var(--tw-bg-opacity))}.group:hover .group-hover\:text-muted-light{--tw-text-opacity:1;color:rgb(168 162 158/var(--tw-text-opacity))}@media (min-width:640px){.sm\:mr-2{margin-right:0.5rem}}@media (min-width:768px){.md\:mt-24{margin-top:6rem}.md\:space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.md\:text-5xl{font-size:3rem;line-height:1}}.dark\:bg-accent-dark:where(.dark,.dark *){--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.dark\:bg-muted-dark:where(.dark,.dark *){--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity))}.dark\:text-accent-dark:where(.dark,.dark *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark\:hover\:bg-violet-950:hover:where(.dark,.dark *){--tw-bg-opacity:1;background-color:rgb(46 16 101/var(--tw-bg-opacity))}.dark\:hover\:text-muted-dark:hover:where(.dark,.dark *){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.group:hover .dark\:group-hover\:bg-secondary-dark:where(.dark,.dark *){--tw-bg-opacity:1;background-color:rgb(76 29 149/var(--tw-bg-opacity))}.group:hover .dark\:group-hover\:text-muted-dark:where(.dark,.dark *){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.group:hover .group-hover\:dark\:text-muted-dark:where(.dark,.dark *){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))} diff --git a/out/bundle.js b/out/bundle.js new file mode 100644 index 0000000..4602406 --- /dev/null +++ b/out/bundle.js @@ -0,0 +1 @@ +const e=window.matchMedia("(prefers-color-scheme: dark)").matches,t=()=>{document.documentElement.classList.remove("dark")},s=()=>{document.documentElement.classList.add("dark")};let o="dark"===localStorage.getItem("theme")?2:"light"===localStorage.getItem("theme")?1:0;const a=document.getElementById("theme-toggle");a.addEventListener("click",(()=>{switch(o=(o+1)%3,o){case 0:localStorage.removeItem("theme"),e?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark"),a.innerText="theme: system";break;case 1:e?(localStorage.setItem("theme","light"),t(),a.innerText="theme: light"):(localStorage.setItem("theme","dark"),s(),a.innerText="theme: dark");break;case 2:e?(localStorage.setItem("theme","dark"),s(),a.innerText="theme: dark"):(localStorage.setItem("theme","light"),t(),a.innerText="theme: light")}}));const n=()=>{document.body.classList.remove("font-sans"),document.body.classList.remove("font-serif")},m=e=>{e&&"serif"===e&&(n(),document.body.classList.add("font-serif")),e&&"sans"===e&&(n(),document.body.classList.add("font-sans")),e||n()};let c=localStorage.getItem("font");m();const l=document.getElementById("font-toggle");l.addEventListener("click",(()=>{c=localStorage.getItem("font"),"sans"===c?(c="serif",l.innerText="serif",localStorage.setItem("font","serif")):(c="sans",l.innerText="sans",localStorage.setItem("font","sans")),m(c)})); diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/rss.xml b/rss.xml new file mode 100644 index 0000000..b622278 --- /dev/null +++ b/rss.xml @@ -0,0 +1,122 @@ + + + + gradient ascent + https://blog.youwen.dev + + + 2024-05-25T12:00:00Z + + why I made my blog in haskell + https://blog.youwen.dev/why-i-made-my-blog-in-haskell.html + +
+

+ why I made my blog in haskell +

+

+ a purely functional...blog? +

+
2024-05-25
+
+ (last updated: 2024-05-25T12:00:00Z) +
+
+

Welcome! This is the first post on gradient ascent and also one that tests all +of the features.

+

gradient ascent

+

I’ll be writing about computers, code, math, video games, and whatever else +here.

+
+

A monad is just a monoid in the category of endofunctors, what’s the problem?

+
+

haskell?

+

This entire blog is generated with hakyll. It’s +a library for generating static sites for Haskell, a purely functional +programming language. It’s a library because it doesn’t come with as many +batteries included as tools like Hugo or Astro. You set up most of the site +yourself by calling the library from Haskell.

+

Here’s a brief excerpt:

+
main :: IO ()
+main = hakyllWith config $ do
+    forM_
+        [ "CNAME"
+        , "favicon.ico"
+        , "robots.txt"
+        , "_config.yml"
+        , "images/*"
+        , "out/*"
+        , "fonts/*"
+        ]
+        $ \f -> match f $ do
+            route idRoute
+            compile copyFileCompiler
+

The code highlighting is also generated by hakyll.

+
+

why?

+

Haskell is a purely functional language with no mutable state. Its syntax +actually makes it pretty elegant for declaring routes and “rendering” pipelines.

+

I originally wanted to build this entire blog myself. I had a working version +with the Svelte framework, complete with GFM rendering, table of contents, KaTeX +math, code highlighting, static generation, and other goodies. However, it +seemed like a little too much work to maintain. I switched to hakyll because

+
    +
  1. Haskell is cool.
  2. +
  3. It comes with enough features that I don’t feel like I have to build +everything from scratch.
  4. +
  5. It comes with Pandoc, a Haskell library for converting between markdown +formats. It’s probably more powerful than anything you could do in nodejs. +It renders all of the markdown to HTML as well as the math. +
      +
    1. It supports KaTeX as well as MathML. I’m a little disappointed with the +KaTeX though. It doesn’t directly render it, but simply injects the KaTeX +files and renders it client-side.
    2. +
  6. +
+

speaking of math

+

We can have math inline, like so: +ex2dx=π\int_\infty^\infty \, e^{-x^2}\,dx = \sqrt{\pi}. This site ships semantic +MathML math with its HTML, and the MathJax script to the client.

+

It’d be nice if MathML could just be used and supported across all browsers, but +unfortunately we still aren’t quite there yet. Firefox is the only one where +everything looks 80% of the way to LaTeX. On Safari and Chrome, even simple +equations like π\sqrt{\pi} render improperly.

+

Pros of MathML:

+
    +
  • A little more accessible
  • +
  • Can be rendered without additional stylesheets. I just installed the Latin +Modern font, but this isn’t even really necessary
  • +
  • Built-in to most browsers (#UseThePlatform)
  • +
+

Cons:

+
    +
  • Isn’t fully standardized. Might look different on different browsers
  • +
  • Rendering quality isn’t as good as KaTeX
  • +
+

This site has MathJax render all of the math so it looks nice and standardized +across browsers, but the math still displays regardless (like say if MathJax +couldn’t load due to slow network) because of MathML. Best of both worlds.

+

Let’s try it now. Here’s a simple theorem:

+

an+bncn{a,b,c}n3 +a^n + b^n \ne c^n \, \forall\,\left\{ a,\,b,\,c \right\} \in \mathbb{Z} \land n \ge 3 +

+

The proof is trivial and will be left as an exercise to the reader.

+

seems a little overengineered

+

Probably is. Not as much as the old one, though.

+ +]]>
+ Sat, 25 May 2024 00:00:00 UT + https://blog.youwen.dev/why-i-made-my-blog-in-haskell.html + Youwen Wu +
+ +
+
diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..71d34cd --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,16 @@ + + + + https://blog.youwen.dev + daily + 1.0 + + + + https://blog.youwen.dev/why-i-made-my-blog-in-haskell.html + 2024-05-25T12:00:00Z + weekly + 0.8 + + + diff --git a/why-i-made-my-blog-in-haskell.html b/why-i-made-my-blog-in-haskell.html new file mode 100644 index 0000000..103f378 --- /dev/null +++ b/why-i-made-my-blog-in-haskell.html @@ -0,0 +1,276 @@ + + + + why I made my blog in haskell | gradient ascent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

+ Gradient Ascent. +

+
+
+

+ a web-log about computers, math, hacks, and all the rest. +

+ by Youwen Wu + | + + | + +
+
+
+

+ why I made my blog in haskell +

+

+ a purely functional...blog? +

+
2024-05-25
+
+ (last updated: 2024-05-25T12:00:00Z) +
+
+

Welcome! This is the first post on gradient ascent and also one that tests all +of the features.

+

gradient ascent

+

I’ll be writing about computers, code, math, video games, and whatever else +here.

+
+

A monad is just a monoid in the category of endofunctors, what’s the problem?

+
+

haskell?

+

This entire blog is generated with hakyll. It’s +a library for generating static sites for Haskell, a purely functional +programming language. It’s a library because it doesn’t come with as many +batteries included as tools like Hugo or Astro. You set up most of the site +yourself by calling the library from Haskell.

+

Here’s a brief excerpt:

+
main :: IO ()
+main = hakyllWith config $ do
+    forM_
+        [ "CNAME"
+        , "favicon.ico"
+        , "robots.txt"
+        , "_config.yml"
+        , "images/*"
+        , "out/*"
+        , "fonts/*"
+        ]
+        $ \f -> match f $ do
+            route idRoute
+            compile copyFileCompiler
+

The code highlighting is also generated by hakyll.

+
+

why?

+

Haskell is a purely functional language with no mutable state. Its syntax +actually makes it pretty elegant for declaring routes and “rendering” pipelines.

+

I originally wanted to build this entire blog myself. I had a working version +with the Svelte framework, complete with GFM rendering, table of contents, KaTeX +math, code highlighting, static generation, and other goodies. However, it +seemed like a little too much work to maintain. I switched to hakyll because

+
    +
  1. Haskell is cool.
  2. +
  3. It comes with enough features that I don’t feel like I have to build +everything from scratch.
  4. +
  5. It comes with Pandoc, a Haskell library for converting between markdown +formats. It’s probably more powerful than anything you could do in nodejs. +It renders all of the markdown to HTML as well as the math. +
      +
    1. It supports KaTeX as well as MathML. I’m a little disappointed with the +KaTeX though. It doesn’t directly render it, but simply injects the KaTeX +files and renders it client-side.
    2. +
  6. +
+

speaking of math

+

We can have math inline, like so: +ex2dx=π\int_\infty^\infty \, e^{-x^2}\,dx = \sqrt{\pi}. This site ships semantic +MathML math with its HTML, and the MathJax script to the client.

+

It’d be nice if MathML could just be used and supported across all browsers, but +unfortunately we still aren’t quite there yet. Firefox is the only one where +everything looks 80% of the way to LaTeX. On Safari and Chrome, even simple +equations like π\sqrt{\pi} render improperly.

+

Pros of MathML:

+ +

Cons:

+ +

This site has MathJax render all of the math so it looks nice and standardized +across browsers, but the math still displays regardless (like say if MathJax +couldn’t load due to slow network) because of MathML. Best of both worlds.

+

Let’s try it now. Here’s a simple theorem:

+

an+bncn{a,b,c}n3 +a^n + b^n \ne c^n \, \forall\,\left\{ a,\,b,\,c \right\} \in \mathbb{Z} \land n \ge 3 +

+

The proof is trivial and will be left as an exercise to the reader.

+

seems a little overengineered

+

Probably is. Not as much as the old one, though.

+
+ + + + +