Skip to content

Instantly share code, notes, and snippets.

@lovasoa
Last active March 4, 2016 21:07
Show Gist options
  • Save lovasoa/70657ac8616f7a7906e1 to your computer and use it in GitHub Desktop.
Save lovasoa/70657ac8616f7a7906e1 to your computer and use it in GitHub Desktop.
A little HTML tree editor in Elm, that I did as my first exercise in the language
import Html exposing (Html, Attribute, text, toElement, div, input)
import Html.Attributes exposing (..)
import Html.Events exposing (on, targetValue)
import Signal exposing (Address)
import StartApp.Simple as StartApp
import Debug
type Tree a
= Empty
| Node a (Tree a) (Tree a)
empty : Tree a
empty =
Empty
singleton : a -> Tree a
singleton v =
Node v Empty Empty
insert : comparable -> Tree comparable -> Tree comparable
insert x tree =
case tree of
Empty ->
singleton x
Node y left right ->
if x > y then
Node y left (insert x right)
else if x < y then
Node y (insert x left) right
else
tree
fromList : List comparable -> Tree comparable
fromList xs = List.foldl insert empty xs
{-- reduce with a reduce and a rereduce functions --}
reduceWith : (b -> b -> c) -> (a -> c -> b) -> b -> Tree a -> b
reduceWith rereduce reduce init tree =
case tree of
Empty -> init
Node v left right ->
let rr = reduceWith rereduce reduce init
in reduce v (rereduce (rr left) (rr right))
map : (a -> b) -> Tree a -> Tree b
map f = reduceWith (\l r -> (l, r)) (\v (l, r) -> Node (f v) l r) Empty
depth : Tree a -> Int
depth = reduceWith Basics.max (\_ n -> n+1) 0
flatten : Tree a -> List a
flatten = reduceWith (++) (::) []
fold : (a -> b -> b) -> b -> Tree a -> b
fold f init tree = List.foldr f init (flatten tree)
sum : Tree number -> number
sum = fold (+) 0
isElement : a -> Tree a -> Bool
isElement k = fold (\v r -> v == k || r) False
t1 = fromList [1,2,3]
t2 = fromList [2,1,3]
main =
StartApp.start { model = Empty, view = view', update = update }
update: (List Int, String) -> Tree String -> Tree String
update (path,val) oldTree =
case path of
[] -> case oldTree of
Empty -> Node val Empty Empty
Node _ l r -> Node val l r
lr :: rpath -> case oldTree of
Empty -> Empty {-- invalid path --}
Node vv l r -> if lr == 0
then Node vv (update (rpath, val) l) r
else Node vv l (update (rpath, val) r)
view : List Int -> Address (List Int, String) -> Tree String -> Html
view path adress tree = let full = path==[] in
case tree of
Empty -> div [myStyle full]
[input
[
style [("width", "40%")],
placeholder "Nouvelle valeur",
on "input" targetValue (\s -> Signal.message adress (path,s))
]
[]
]
Node v l r -> div [myStyle full]
[
input [ style [("width", "90%")],
value v,
on "input" targetValue (\s -> Signal.message adress (path,s))
]
[],
div [] [
view (path++[0]) adress l,
view (path++[1]) adress r
]
]
view' : Address (List Int, String) -> Tree String -> Html
view' = view []
myStyle full =
style
[ ("width", if full then "100%" else "45%")
, ("border", "1px solid black")
, ("display", "inline-block")
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment