I’ve been working on a web photo album in Elm, and I think it’s finally ready for others to take a look, provide feedback, and help out a bit if you’re interested!
I think it has a couple of interesting aspects to it:
I used this project as my introduction to learning Elm. So, if you look at the git commit history, you can see some interesting examples of things I struggled with, ways that I changed my mind, et cetera. There’s a longer essay to be written on this topic, for sure!
I didn’t want to require anything but static files on the server side, so it has a pre-processing step that creates thumbnails of the images and a JSON file describing the structure of the nested sub-albums. I wrote that pre-processing code in Haskell. I used the excellent elm-bridge Haskell library to generate elm versions of the shared data types as well as JSON decoders for them.
Finally, I’ve used Nix to ease development by automatically managing dependencies and creating reproducible development environments. It’s a really cool tool, and I encourage everyone to check it out! (I’m also hoping that 0.19 contains some features that will make Elm more Nix-friendly.)
Anyway, thanks for reading, I’m happy to answer questions, and I hope others find this useful in one way or another!
I love the static-files-only approach! I’ve been working on some apps that use that approach as well (though can store dynamic data in Dropbox). If organizing my photos ever gets to the top of my todo list I’ll have to try it out
Hey, this is really cool! The mix of technologies gives plenty of nice ideas to think about. I’m curious about the shared data structures; are they mostly driven by Haskell, with Elm conforming to using them, or are there times where you go back and change the data on the Haskell side, to make things better on the Elm side?
I think the languages are similar enough, and my type needs are simple enough, that I didn’t feel like either language really drove the shared data structures – rather, I tried to let the problem domain drive the types. (I feel like that’s the approach that both languages encourage in their docs anyway.) You can see below that the Haskell and Elm types line up almost exactly, and if it’d happened that someone had written an elm -> haskell bridge instead of a haskell -> elm bridge, I don’t think it would’ve changed much for me.
Maybe the only example of what you’re talking about arose because of the way Elm’s List.head works differently than Haskell’s: in Elm, it produces a Maybe a (in case the list is empty), while in Haskell, it produces an a (and throws an exception if the list is empty).
I’d originally said that an album was a record with a field images : (List Image). But I found myself writing several bits of Elm code where it wasn’t obvious how to deal with the empty list (in Haskell I could’ve ignored that and let the exception be thrown, I guess). And I watched the “make impossible states impossible” talk by Richard around that same time. So that led me to switch to a pair of fields, imageFirst : Image, imageRest : (List Image), basically declaring that I know I’m always going to have at least one image. That made the Elm code a lot simpler (without much impact at all on the Haskell code).
Haskell (written by hand)
Elm (produced by elm-bridge)
data ImgSrc
= ImgSrc
{ url :: String
, x :: Int
, y :: Int
} deriving (Generic, Show, Eq)
type alias ImgSrc =
{ url: String
, x: Int
, y: Int
}
data NodeOrAlbum
= Subtree AlbumTreeNode
| Leaf Album
deriving (Generic, Show, Eq)
type NodeOrAlbum =
Subtree AlbumTreeNode
| Leaf Album
I have a similar static gallery implmentation using simple React + Redux which requires pre-processing image info into a static JSON file while generating a new build.
As you already have it implemented in Elm, I will probably just study Elbum's code and see if I can collaborate on anything. Otherwise, I will just ask for your help if I need any while rewriting my static-gallery project.