Skip to content

Commit bcdb705

Browse files
author
Sjoerd Visscher
committed
Generate cleaner haskell arrow code
1 parent c7b8773 commit bcdb705

2 files changed

Lines changed: 35 additions & 24 deletions

File tree

src/Output/Haskell.purs

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,29 @@ import Control.Monad.Free (Free, liftF, wrap)
66
import Data.Array (intercalate, singleton, replicate, uncons)
77
import Data.Foldable (foldMap, foldl, length)
88
import Data.FoldableWithIndex (foldMapWithIndex)
9-
import Data.Set as Set
9+
import Data.Map as Map
1010
import Data.Maybe (maybe)
11-
import Data.String (toLower, contains)
12-
import Data.String.Pattern (Pattern(..))
11+
import Data.String (toLower, contains, replaceAll, Pattern(..), Replacement(..))
1312
import Data.Traversable (mapAccumL)
1413
import Data.Tuple.Nested ((/\))
1514

1615
import Common
1716
import Model
1817

19-
haskellCode :: TypedTerm String String -> String
20-
haskellCode tm = case haskellCode' tm of
21-
{ i, o, code } -> args <> arr (tuple $ foldMap singleton i) (showNested i) `comp` code `comp` arr (showNested o) (tuple $ foldMap singleton o)
18+
19+
haskellCode :: String -> TypedTerm String String -> String
20+
haskellCode name tm = case haskellCode' tm of
21+
{ i, o, code } -> typeDecl <> args <> indent ("\n" <> arr (tuple $ foldMap singleton i) (showNested i) `comp` code `comp` arr (showNested o) (tuple $ foldMap singleton o))
2222
where
23-
gens = foldMap (\{ decl, bid } -> if isGen decl then Set.singleton bid else Set.empty) tm
24-
args = if length gens > 0 then "\\" <> toLower (intercalate " " gens) <> " -> " else ""
23+
gens = tm # foldMap \{ decl, bid } -> case decl of
24+
Gen ty -> Map.singleton bid ty
25+
otherwise -> Map.empty
26+
args = if length gens > 0 then name <> " " <> toLower (intercalate " " $ Map.keys gens) <> " = " else ""
27+
typeDecl = name <>
28+
"\n :: Arrow arr" <>
29+
"\n => " <> intercalate "\n -> " (showTy <$> Map.values gens) <>
30+
"\n -> " <> showTy (getAnn tm) <>
31+
"\n"
2532

2633

2734
type HaskellCode = { i :: Free Array String, o :: Free Array String, code :: String }
@@ -41,42 +48,43 @@ haskellCode' = foldFix \(Ann _ f) -> alg f where
4148
o = 0 ..< r <#> \n -> "o" <> show n
4249
out = if l == 1
4350
then tuple (replicate r "i0")
44-
else "let o = mconcat [" <> intercalate ", " i <> "] in " <> tuple (replicate r "o")
51+
else "let o = merge [" <> intercalate ", " i <> "] in " <> tuple (replicate r "o")
4552
Gen (Ty i o) ->
4653
{ i: liftF $ foldMapWithIndex (\j n -> [toLower n <> show j]) i
4754
, o: liftF $ foldMapWithIndex (\j n -> [toLower n <> show j]) o
4855
, code: toLower bid }
49-
Cup -> haskellEmpty -- TODO
50-
Cap -> haskellEmpty
51-
alg (TC ts) = ts # uncons # maybe haskellEmpty \{ head, tail } -> foldl compose head tail
56+
Cup -> { i: liftF [], o: liftF ["a0", "a1"], code: "cup" }
57+
Cap -> { i: liftF ["a0", "a1"], o: liftF [], code: "cap" }
58+
alg (TC ts) = ts # uncons # maybe haskellEmpty (\{ head, tail } -> foldl compose head tail) # mapCode braced
5259
where
53-
compose l r = { i: l.i, o: r.o, code : braced $ l.code `comp` arr (showNested l.o) (showNested i') `comp` r.code }
60+
compose l r = { i: l.i, o: r.o, code : l.code `comp` arr (showNested l.o) (showNested i') `comp` r.code }
5461
where
5562
os = foldMap singleton l.o
5663
i' = mapAccumL accum os r.i # _.value
5764
accum os' _ = uncons os' # maybe { accum: [], value: "_" } \{ head, tail } -> { accum: tail, value: head }
5865
alg (TT ts) = foldMapWithIndex f ts # g
5966
where
60-
f j { i, o, code } =
61-
[{ i: map (\n -> n <> "_" <> show j) i
62-
, o: map (\n -> n <> "_" <> show j) o
63-
, code
64-
}]
65-
g l = uncons l # maybe haskellEmpty \{ head, tail } -> foldl tensor head tail
66-
tensor :: HaskellCode -> HaskellCode -> HaskellCode
67+
f j { i, o, code } = [{ i: map (\n -> n <> "_" <> show j) i, o: map (\n -> n <> "_" <> show j) o, code }]
68+
g l = uncons l # maybe haskellEmpty (\{ head, tail } -> foldl tensor head tail)
6769
tensor l r =
6870
{ i: wrap [l.i, r.i]
6971
, o: wrap [l.o, r.o]
70-
, code: "(" <> l.code <> " *** " <> r.code <> ")"
72+
, code: braced (l.code <> " *** " <> r.code)
7173
}
7274

75+
mapCode :: (String -> String) -> HaskellCode -> HaskellCode
76+
mapCode f { i, o, code } = { i, o, code: f code }
77+
7378
comp :: String -> String -> String
7479
comp "returnA" r = r
7580
comp l "returnA" = l
76-
comp l r = l <> " >>> " <> r
81+
comp l r = l <> "\n>>> " <> r
82+
83+
indent :: String -> String
84+
indent = replaceAll (Pattern "\n") (Replacement "\n ")
7785

7886
braced :: String -> String
79-
braced s = if contains (Pattern " ") s then "(" <> s <> ")" else s
87+
braced s = if contains (Pattern " ") s then "(" <> (if contains (Pattern "\n") s then indent s else s) <> ")" else s
8088

8189
arr :: String -> String -> String
8290
arr ls rs = if ls == rs then "returnA" else "arr (\\" <> ls <> " -> " <> rs <> ")"
@@ -87,3 +95,6 @@ tuple ss = "(" <> intercalate ", " ss <> ")"
8795

8896
showNested :: Free Array String -> String
8997
showNested = foldFree tuple identity
98+
99+
showTy :: Ty String -> String
100+
showTy (Ty l r) = "arr " <> tuple l <> " " <> tuple r

src/View/App.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ render st = div [ classes [ ClassName "app" ] ]
102102
, div_ $ inferredType # either (const []) (\{ term } ->
103103
[ button [ onClick \_ -> Just (CopyToClipboard $ json term) ]
104104
[ text "JSON" ]
105-
, button [ onClick \_ -> Just (CopyToClipboard $ haskellCode term) ]
105+
, button [ onClick \_ -> Just (CopyToClipboard $ haskellCode "diagram" term) ]
106106
[ text "Haskell" ]
107107
])
108108
]

0 commit comments

Comments
 (0)