Skip to content

Commit e1ee65d

Browse files
committed
Add helper for constructing builtins.
1 parent 835269c commit e1ee65d

File tree

4 files changed

+51
-13
lines changed

4 files changed

+51
-13
lines changed

package.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extra-source-files:
2020
description: Please see the README on GitHub at <https://github.com/githubuser/haskenthetical#readme>
2121

2222
default-extensions:
23+
- ApplicativeDo
2324
- DataKinds
2425
- DeriveGeneric
2526
- FlexibleContexts

src/Defaults.hs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,21 @@ hcdr :: Val -> Either Text Val
3939
hcdr (Tag "," [_, b]) = Right b
4040
hcdr _ = Left "cdr only accepts pairs"
4141

42-
heither :: Val -> Either Text Val
43-
heither l = rbb "either.1" $ \r -> rbb "either.2" $ \case
44-
Tag "Left" [v] -> call l v
45-
Tag "Right" [v] -> call r v
46-
_ -> Left "final argument of either must be an Either"
42+
heither :: Val
43+
heither = mkBuiltinUnsafe $ do
44+
l <- getArg "either"
45+
r <- getArg "either.1"
46+
e <- getArg "either.2"
47+
pure $ case e of
48+
Tag "Left" [v] -> call l v
49+
Tag "Right" [v] -> call r v
50+
_ -> Left "final argument of either must be an Either"
4751

4852
hif0 :: Val -> Either Text Val
49-
hif0 (Float v) = rbb "if0.1" $ \then_ -> rbb "if0.2" $ \else_ ->
50-
if v == 0 then Right then_ else Right else_
53+
hif0 (Float v) = mkBuiltin $ do
54+
then_ <- getArg "if0.1"
55+
else_ <- getArg "if0.2"
56+
pure $ Right $ if v == 0 then then_ else else_
5157
hif0 _ = Left "first arg to if0 must be a Float"
5258

5359
defaultVarEnv :: Map Name (PType Tc, Val)
@@ -65,7 +71,7 @@ defaultVarEnv = fmap (\(x, y) -> (y, x)) $ Map.fromList
6571
~~ bb "Right" (Right . Tag "Right" . (: []))
6672
~~ Forall [a', b'] (b +-> (a +:+ b))
6773
, "either"
68-
~~ bb "either" heither
74+
~~ heither
6975
~~ Forall [a', b', c'] ((a +-> c) +-> (b +-> c) +-> (a +:+ b) +-> c)
7076
, "if0" ~~ bb "if0" hif0 ~~ Forall [a'] (tFloat +-> a +-> a +-> a)
7177
]

src/Env.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ declareTypeConstructors (TypeDecl' { tdName, tdVars, tdConstructors }) env = do
9696
newVars = foldM
9797
(\vars (conName, argNames) -> do
9898
ty <- conType argNames
99-
val <- conVal conName argNames
99+
let val = conVal conName argNames
100100
insertUnique (CEMultiDeclareConstructor conName) conName (ty, val) vars
101101
)
102102
(feVars env) tdConstructors
@@ -118,13 +118,14 @@ declareTypeConstructors (TypeDecl' { tdName, tdVars, tdConstructors }) env = do
118118

119119
return $ Forall allVars $ foldr (+->) finalType types
120120

121-
conVal :: Name -> [MType Ps] -> Either CompileError Val
122-
conVal conName ts = return $ go [] 0 (length ts)
121+
conVal :: Name -> [MType Ps] -> Val
122+
conVal conName ts = go [] 0 (length ts)
123123
where
124124
go :: [Val] -> Int -> Int -> Val
125125
go acc _ 0 = Tag conName acc
126-
go acc d n = Builtin $ Builtin' (mkName d) $ \v ->
127-
Right $ go (acc ++ [v]) (d + 1) (n - 1)
126+
go acc d n = mkBuiltinUnsafe $ do
127+
v <- getArg (mkName d)
128+
pure $ Right $ go (acc ++ [v]) (d + 1) (n - 1)
128129

129130
mkName 0 = conName
130131
mkName n = conName <> "." <> Name (tshow n)

src/Syntax.hs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ module Syntax
2020
, extractType
2121
, mkTyped
2222
, rmType
23+
24+
, DoBuiltin(..), getArg, mkBuiltin, mkBuiltinUnsafe
2325
) where
2426

2527
import Prelude.Extra
@@ -62,6 +64,34 @@ instance Show Builtin where
6264
instance Eq Builtin where
6365
Builtin' n1 _ == Builtin' n2 _ = n1 == n2
6466

67+
-- | A helper type to let us construct `Builtin` with do notation. Use with
68+
-- `getArg` and `mkBuiltin`.
69+
--
70+
-- There's no Monad instance for this, and there can't be. Needs ApplicativeDo.
71+
-- Some other datatype might let us achieve the same goal with more generality.
72+
data DoBuiltin a = DoBuiltin [Name] ([Val] -> a)
73+
74+
instance Functor DoBuiltin where
75+
fmap f (DoBuiltin ns g) = DoBuiltin ns (f . g)
76+
77+
instance Applicative DoBuiltin where
78+
pure a = DoBuiltin [] (const a)
79+
(DoBuiltin ns1 f) <*> (DoBuiltin ns2 g) = DoBuiltin (ns1 ++ ns2) $ \vals ->
80+
let fVals = take (length ns1) vals
81+
gVals = drop (length ns1) vals
82+
in (f fVals) (g gVals)
83+
84+
getArg :: Name -> DoBuiltin Val
85+
getArg n = DoBuiltin [n] head
86+
87+
mkBuiltin :: DoBuiltin (Either Text Val) -> Either Text Val
88+
mkBuiltin (DoBuiltin [] f) = f []
89+
mkBuiltin (DoBuiltin (n1:ns) f) = Right $ Builtin $ Builtin' n1 $ \v ->
90+
mkBuiltin $ DoBuiltin ns (\vs -> f (v : vs))
91+
92+
mkBuiltinUnsafe :: DoBuiltin (Either Text Val) -> Val
93+
mkBuiltinUnsafe = either (error "Bad DoBuiltin") id . mkBuiltin
94+
6595
newtype Env = Env { unEnv :: Map Name Val }
6696
deriving (Eq, Show)
6797

0 commit comments

Comments
 (0)