diff --git a/src/Urbit/Deconstructor.elm b/src/Urbit/Deconstructor.elm index 9afa9a2..4a9f31c 100644 --- a/src/Urbit/Deconstructor.elm +++ b/src/Urbit/Deconstructor.elm @@ -1,17 +1,21 @@ module Urbit.Deconstructor exposing ( Deconstructor , alt + , bytes , cell + , const + , cord , float32 , float64 , int , list , llec , map + , oneOf , run , runBytes , sig - , string + , tape , tar ) @@ -38,8 +42,25 @@ runBytes (Deconstructor f) bs = (\noun -> f noun identity) -string : Deconstructor (String -> a) a -string = +const : Deconstructor (a -> a) a -> a -> Deconstructor c c +const (Deconstructor f) value = + Deconstructor + (\noun c -> + case f noun identity of + Just a -> + if a == value then + Just c + + else + Nothing + + Nothing -> + Nothing + ) + + +cord : Deconstructor (String -> a) a +cord = Deconstructor (\x f -> case x of @@ -52,6 +73,11 @@ string = ) +tape : Deconstructor (String -> a) a +tape = + list cord |> fmap String.concat + + int : Deconstructor (Int -> a) a int = Deconstructor @@ -158,6 +184,16 @@ alt (Deconstructor f) (Deconstructor g) = ) +oneOf : List (Deconstructor a b) -> Deconstructor a b +oneOf l = + case l of + [] -> + Deconstructor (\_ _ -> Nothing) + + x :: xs -> + alt x (oneOf xs) + + tar : Deconstructor a a tar = Deconstructor (\_ a -> Just a) @@ -192,3 +228,8 @@ cell (Deconstructor l) (Deconstructor r) = map : a -> Deconstructor a b -> Deconstructor (b -> c) c map a (Deconstructor f) = Deconstructor (\noun g -> f noun a |> Maybe.map g) + + +fmap : (a -> b) -> Deconstructor (a -> c) c -> Deconstructor (b -> c) c +fmap f (Deconstructor g) = + Deconstructor (\noun h -> g noun (f >> h)) diff --git a/tests/Test/Urbit.elm b/tests/Test/Urbit.elm index 9e44dad..6d966f4 100644 --- a/tests/Test/Urbit.elm +++ b/tests/Test/Urbit.elm @@ -93,6 +93,52 @@ tests = (Bytes.fromByteValues [ 0x01, 0x1F, 0x00, 0x00, 0x20, 0x08, 0x7C, 0x00, 0x00, 0x98, 0x20 ]) ) ) + , test "[8 'hi']" + (\() -> + Expect.equal + (Just ( 8, "hi" )) + (D.runBytes + (D.cell D.int D.cord |> D.map Tuple.pair) + (Bytes.fromByteValues [ 0x41, 0x10, 0x3C, 0x5A, 0x1A ]) + ) + ) + , test "[8 \"hi\"]" + (\() -> + Expect.equal + (Just ( 8, "hi" )) + (D.runBytes + (D.cell D.int D.tape |> D.map Tuple.pair) + (Bytes.fromByteValues [ 0x41, 0x30, 0x38, 0x3A, 0x78, 0x5A ]) + ) + ) + , describe "sum types" + [ test "[%tape \"hi\"]" + (\() -> + Expect.equal + (Just "hi") + (D.runBytes + (D.oneOf + [ D.cell (D.const D.cord "tape") D.tape + , D.cell (D.const D.cord "cord") D.cord + ] + ) + (Bytes.fromByteValues [ 0x01, 0x9F, 0x2E, 0x0C, 0xAE, 0x1C, 0x1C, 0x1D, 0x3C, 0x2D ]) + ) + ) + , test "[%cord 'hi']" + (\() -> + Expect.equal + (Just "hi") + (D.runBytes + (D.oneOf + [ D.cell (D.const D.cord "tape") D.tape + , D.cell (D.const D.cord "cord") D.cord + ] + ) + (Bytes.fromByteValues [ 0x01, 0x7F, 0xEC, 0x4D, 0x8E, 0x0C, 0x1E, 0x2D, 0x0D ]) + ) + ) + ] ] ]