Skip to content

Instantly share code, notes, and snippets.

@bergmark
Last active April 9, 2022 14:41
Show Gist options
  • Save bergmark/5076c0408c086467239b4f45073ea931 to your computer and use it in GitHub Desktop.
Save bergmark/5076c0408c086467239b4f45073ea931 to your computer and use it in GitHub Desktop.
Parsing JSON in Haskell vs Rust
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeApplications #-}
module Compiler (Version, Compiler) where
import Control.Monad ((<=<))
import Data.Aeson (FromJSON (..))
data Version = Version String
data Compiler = Compiler { version :: Version }
instance TryFrom String Compiler where
type Error String Compiler = String
tryFrom = Right . Compiler . Version
instance FromJSON Compiler where
parseJSON = either fail pure . tryFrom <=< parseJSON @String
-- Mimicking rust's stdlib
class TryFrom a b where
type Error a b
tryFrom :: a -> Either (Error a b) b
use serde::{Deserialize, Deserializer};
pub struct Version(String);
pub struct Compiler {
version: Version
}
impl TryFrom<&str> for Compiler {
type Error = String;
fn try_from(s: &str) -> Result<Self, String> {
Ok(Compiler { version: Version(s.to_owned()) })
}
}
impl<'de> Deserialize<'de> for Compiler {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(deserializer)?;
s.try_into().map_err(serde::de::Error::custom)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment