Did a lot. Not sure it compiles. Tried Laziness
This commit is contained in:
parent
520e314dbb
commit
d6ea01b330
8 changed files with 259 additions and 132 deletions
|
@ -21,28 +21,3 @@ step : Automaton s i -> Maybe s -> i -> Maybe s
|
||||||
step ls s0 i = case s0 of
|
step ls s0 i = case s0 of
|
||||||
Nothing -> Nothing
|
Nothing -> Nothing
|
||||||
Just s -> List.filter (\((t, j), b) -> t == s && i == j) ls |> List.head |> Maybe.map snd
|
Just s -> List.filter (\((t, j), b) -> t == s && i == j) ls |> List.head |> Maybe.map snd
|
||||||
|
|
||||||
--(=>) = (,)
|
|
||||||
|
|
||||||
--state2Color : State -> Color
|
|
||||||
--state2Color s = case s of
|
|
||||||
-- Nothing -> Color.black
|
|
||||||
-- Just n -> hsl (degrees (toFloat n)*77) 1.0 (0.8 - 0.6 * (toFloat n)/size)
|
|
||||||
|
|
||||||
--color2String : Color -> String
|
|
||||||
--color2String c = let rgb = toRgb c in "rgb(" ++ toString rgb.red ++ ", " ++ toString rgb.green ++ ", " ++ toString rgb.blue ++ ")"
|
|
||||||
|
|
||||||
--block : Color -> Html msg
|
|
||||||
--block c = div [style ["background-color" => color2String c, "width" => "100px", "height" => "100px", "display" => "inline-block"]] []
|
|
||||||
|
|
||||||
--view : Model -> Html Msg
|
|
||||||
--view model =
|
|
||||||
-- div []
|
|
||||||
-- ( button [ onClick Regen ] [ text "Regenerate" ]
|
|
||||||
-- :: button [ onClick Sort ] [ text "Sort" ]
|
|
||||||
-- :: br [] []
|
|
||||||
-- :: List.map (block << state2Color) model.states
|
|
||||||
-- )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
38
Grid.elm
38
Grid.elm
|
@ -1,26 +1,26 @@
|
||||||
module Grid exposing (..)
|
module Grid exposing (..)
|
||||||
|
|
||||||
import RingList exposing (..)
|
import Zipper exposing (..)
|
||||||
|
|
||||||
type alias Grid a = RingList (RingList a)
|
type alias Grid a = Zipper (Zipper a)
|
||||||
|
|
||||||
{- Basic conversion -}
|
{- Basic conversion -}
|
||||||
generate : Int -> Int -> (Int -> Int -> a) -> Grid a
|
generate : Int -> Int -> (Int -> Int -> a) -> Grid a
|
||||||
generate width height gen = let
|
generate width height gen = let
|
||||||
row = RingList.fromList 1 [2..width]
|
row = Zipper.fromList 1 [2..width]
|
||||||
cols = RingList.fromList 1 [2..height]
|
cols = Zipper.fromList 1 [2..height]
|
||||||
grid = RingList.map (\y -> RingList.map (\x -> (x, y)) row) cols
|
grid = Zipper.map (\y -> Zipper.map (\x -> (x, y)) row) cols
|
||||||
in map (uncurry gen) grid
|
in map (uncurry gen) grid
|
||||||
|
|
||||||
toList : Grid a -> List (List a)
|
toList : Grid a -> List (List a)
|
||||||
toList grid = RingList.toList <| RingList.map RingList.toList <| grid
|
toList grid = Zipper.toList <| Zipper.map Zipper.toList <| grid
|
||||||
|
|
||||||
{- Functor like functions -}
|
{- Functor like functions -}
|
||||||
map : (a -> b) -> Grid a -> Grid b
|
map : (a -> b) -> Grid a -> Grid b
|
||||||
map f grid = RingList.map (RingList.map f) grid
|
map f grid = Zipper.map (Zipper.map f) grid
|
||||||
|
|
||||||
edit : (a -> a) -> Grid a -> Grid a
|
edit : (a -> a) -> Grid a -> Grid a
|
||||||
edit f grid = RingList.edit (RingList.edit f) grid
|
edit f grid = Zipper.edit (Zipper.edit f) grid
|
||||||
|
|
||||||
{- Comonad functions -}
|
{- Comonad functions -}
|
||||||
extract : Grid a -> a
|
extract : Grid a -> a
|
||||||
|
@ -30,7 +30,7 @@ extract grid = grid.focus.focus
|
||||||
-- is not the right definition (this would be too simple). With the transpose
|
-- is not the right definition (this would be too simple). With the transpose
|
||||||
-- trick it is quite ok to reason about (draw the diagrams yourself!)
|
-- trick it is quite ok to reason about (draw the diagrams yourself!)
|
||||||
duplicate : Grid a -> Grid (Grid a)
|
duplicate : Grid a -> Grid (Grid a)
|
||||||
duplicate grid = grid |> RingList.map RingList.duplicate |> transpose |> RingList.map RingList.duplicate |> transpose
|
duplicate grid = grid |> Zipper.map Zipper.duplicate |> transpose |> Zipper.map Zipper.duplicate |> transpose
|
||||||
|
|
||||||
extend : (Grid a -> b) -> Grid a -> Grid b
|
extend : (Grid a -> b) -> Grid a -> Grid b
|
||||||
extend f w = map f (duplicate w)
|
extend f w = map f (duplicate w)
|
||||||
|
@ -40,26 +40,26 @@ extend f w = map f (duplicate w)
|
||||||
|
|
||||||
{- Domain functions -}
|
{- Domain functions -}
|
||||||
shiftLeft : Grid a -> Grid a
|
shiftLeft : Grid a -> Grid a
|
||||||
shiftLeft grid = RingList.map RingList.shiftLeft grid
|
shiftLeft grid = Zipper.map Zipper.shiftLeft grid
|
||||||
|
|
||||||
shiftRight : Grid a -> Grid a
|
shiftRight : Grid a -> Grid a
|
||||||
shiftRight grid = RingList.map RingList.shiftRight grid
|
shiftRight grid = Zipper.map Zipper.shiftRight grid
|
||||||
|
|
||||||
shiftUp : Grid a -> Grid a
|
shiftUp : Grid a -> Grid a
|
||||||
shiftUp grid = RingList.shiftLeft grid
|
shiftUp grid = Zipper.shiftLeft grid
|
||||||
|
|
||||||
shiftDown : Grid a -> Grid a
|
shiftDown : Grid a -> Grid a
|
||||||
shiftDown grid = RingList.shiftRight grid
|
shiftDown grid = Zipper.shiftRight grid
|
||||||
|
|
||||||
transpose : Grid a -> Grid a
|
transpose : Grid a -> Grid a
|
||||||
transpose grid = let
|
transpose grid = let
|
||||||
newBefore grid = List.map RingList.extract grid.before
|
newBefore grid = List.map Zipper.extract grid.before
|
||||||
newAfter grid = List.map RingList.extract grid.after
|
newAfter grid = List.map Zipper.extract grid.after
|
||||||
newFocus rl = RingList (newBefore rl) (extract rl) (newAfter rl)
|
newFocus rl = Zipper (newBefore rl) (extract rl) (newAfter rl)
|
||||||
nb = List.map newFocus <| RingList.iterate1N (List.length grid.focus.before) shiftRight grid
|
nb = List.map newFocus <| Zipper.iterate1N (List.length grid.focus.before) shiftRight grid
|
||||||
nf = newFocus grid
|
nf = newFocus grid
|
||||||
na = List.map newFocus <| RingList.iterate1N (List.length grid.focus.after) shiftLeft grid
|
na = List.map newFocus <| Zipper.iterate1N (List.length grid.focus.after) shiftLeft grid
|
||||||
in RingList nb nf na
|
in Zipper nb nf na
|
||||||
|
|
||||||
getNeighbours : Grid a -> List a
|
getNeighbours : Grid a -> List a
|
||||||
getNeighbours grid =
|
getNeighbours grid =
|
||||||
|
|
65
Lazy/Zipper.elm
Normal file
65
Lazy/Zipper.elm
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
module Lazy.Zipper exposing (..)
|
||||||
|
|
||||||
|
import Lazy exposing (Lazy)
|
||||||
|
import Lazy.List exposing (LazyList, (:::))
|
||||||
|
|
||||||
|
type alias Zipper a =
|
||||||
|
{ before : LazyList a
|
||||||
|
, focus : Lazy a
|
||||||
|
, after : LazyList a
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{- Basic conversion -}
|
||||||
|
fromList : a -> List a -> Zipper a
|
||||||
|
fromList a l = Zipper Lazy.List.empty (pure a) (Lazy.List.fromList l)
|
||||||
|
|
||||||
|
toList : Zipper a -> List a
|
||||||
|
toList rl = Lazy.List.toList (Lazy.List.reverse rl.before) ++ [Lazy.force rl.focus] ++ Lazy.List.toList rl.after
|
||||||
|
|
||||||
|
{- Functor like things -}
|
||||||
|
map : (a -> b) -> Zipper a -> Zipper b
|
||||||
|
map f rl = Zipper (Lazy.List.map f rl.before) (Lazy.map f rl.focus) (Lazy.List.map f rl.after)
|
||||||
|
|
||||||
|
edit : (a -> a) -> Zipper a -> Zipper a
|
||||||
|
edit f rl = Zipper rl.before (Lazy.map f rl.focus) rl.after
|
||||||
|
|
||||||
|
{- Comonad functions -}
|
||||||
|
extract : Zipper a -> a
|
||||||
|
extract rl = rl.focus |> Lazy.force
|
||||||
|
|
||||||
|
duplicate : Zipper a -> Zipper (Zipper a)
|
||||||
|
duplicate rl = let
|
||||||
|
lefts = iterate1N (Lazy.List.length rl.before) shiftRight rl
|
||||||
|
rights = iterate1N (Lazy.List.length rl.after) shiftLeft rl
|
||||||
|
in Zipper lefts (pure rl) rights
|
||||||
|
|
||||||
|
extend : (Zipper a -> b) -> Zipper a -> Zipper b
|
||||||
|
extend f w = map f (duplicate w)
|
||||||
|
|
||||||
|
(=>>) : Zipper a -> (Zipper a -> b) -> Zipper b
|
||||||
|
(=>>) = flip extend
|
||||||
|
|
||||||
|
{- Domain functions -}
|
||||||
|
shiftLeft : Zipper a -> Zipper a
|
||||||
|
shiftLeft rl = case Lazy.List.headAndTail rl.after of
|
||||||
|
Just (x, xs) -> Zipper (Lazy.force rl.focus ::: rl.before) (pure x) xs
|
||||||
|
Nothing -> case Lazy.List.headAndTail (Lazy.List.reverse rl.before) of
|
||||||
|
Just (x, xs) -> Zipper (Lazy.List.singleton (Lazy.force rl.focus)) (pure x) xs
|
||||||
|
Nothing -> Zipper nil rl.focus nil
|
||||||
|
|
||||||
|
shiftRight : Zipper a -> Zipper a
|
||||||
|
shiftRight rl = case Lazy.List.headAndTail rl.before of
|
||||||
|
Just (x, xs) -> Zipper xs (pure x) (Lazy.force rl.focus ::: rl.after)
|
||||||
|
Nothing -> case Lazy.List.headAndTail (Lazy.List.reverse rl.after) of
|
||||||
|
Just (x, xs) -> Zipper xs (pure x) (Lazy.List.singleton (Lazy.force rl.focus))
|
||||||
|
Nothing -> Zipper nil rl.focus nil
|
||||||
|
|
||||||
|
{- From here we have private functions -}
|
||||||
|
iterate1N : Int -> (a -> a) -> a -> LazyList a
|
||||||
|
iterate1N n f a = case n of
|
||||||
|
0 -> nil
|
||||||
|
m -> f a ::: Lazy.List.map f (iterate1N (m - 1) f a)
|
||||||
|
|
||||||
|
nil = Lazy.List.empty
|
||||||
|
pure x = Lazy.lazy (always x)
|
87
Main.elm
87
Main.elm
|
@ -1,15 +1,15 @@
|
||||||
import Grid exposing (..)
|
|
||||||
import RingList exposing (..)
|
|
||||||
import Automaton exposing (..)
|
import Automaton exposing (..)
|
||||||
|
import Grid exposing (..)
|
||||||
|
import Lazy.Zipper
|
||||||
|
|
||||||
|
import Color exposing (Color)
|
||||||
|
import Dict exposing (Dict)
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
|
||||||
import Html.App as App
|
import Html.App as App
|
||||||
import Html.Events exposing (..)
|
import Html.Attributes exposing (style)
|
||||||
|
import Html.Events exposing (onClick)
|
||||||
import Random
|
import Random
|
||||||
import Color exposing (..)
|
import Time
|
||||||
import Time exposing (Time, second)
|
|
||||||
|
|
||||||
|
|
||||||
main =
|
main =
|
||||||
App.program
|
App.program
|
||||||
|
@ -19,13 +19,13 @@ main =
|
||||||
, subscriptions = subscriptions
|
, subscriptions = subscriptions
|
||||||
}
|
}
|
||||||
|
|
||||||
width = 62
|
width = 34
|
||||||
height = 33
|
height = 31
|
||||||
states = 3
|
states = 10
|
||||||
inputs = 2
|
inputs = 3
|
||||||
outputs = 3
|
outputs = 3
|
||||||
visSize = "20px"
|
visSize = "20px"
|
||||||
freq = 0.3 * second
|
freq = 0.3 * Time.second
|
||||||
|
|
||||||
-- MODEL
|
-- MODEL
|
||||||
|
|
||||||
|
@ -39,16 +39,16 @@ type alias Model =
|
||||||
|
|
||||||
init : (Model, Cmd Msg)
|
init : (Model, Cmd Msg)
|
||||||
init =
|
init =
|
||||||
( { grid = Grid.generate width height initCell
|
( { grid = generate width height initCell
|
||||||
, system = []
|
, system = []
|
||||||
, neighbours = []
|
, neighbours = []
|
||||||
}, Random.generate NewRandomAut (genAut states inputs) )
|
}, Random.generate NewRandomAut (genAut states inputs) )
|
||||||
|
|
||||||
|
|
||||||
initCell x y = case (x > 5, y > 5) of
|
initCell x y = case (x, y) of
|
||||||
(True, _) -> Just 1
|
(18, 16) -> Just 3
|
||||||
(_, True) -> Just 1
|
(17, 16) -> Just 1
|
||||||
_ -> Just (1 + (x + y * width) % states)
|
_ -> Just 2
|
||||||
|
|
||||||
-- UPDATE
|
-- UPDATE
|
||||||
|
|
||||||
|
@ -56,21 +56,50 @@ type Msg
|
||||||
= Update World
|
= Update World
|
||||||
| NewRandomAut AutomatonT
|
| NewRandomAut AutomatonT
|
||||||
| Regen
|
| Regen
|
||||||
|
| Init
|
||||||
| BigStep
|
| BigStep
|
||||||
|
|
||||||
output m = case m of
|
output m = case m of
|
||||||
Nothing -> 1
|
Nothing -> 1
|
||||||
Just s -> 1 + s % outputs
|
Just s -> 1 + s % outputs
|
||||||
|
|
||||||
getNBOutputs grid = let
|
counts : List Int -> Dict Int Int
|
||||||
ret = grid |> Grid.getNeighbours |> List.map output |> List.sum
|
counts ls = let
|
||||||
in 1 + ret % inputs
|
succ n = case n of
|
||||||
|
Just m -> Just (m + 1)
|
||||||
|
Nothing -> Just 1
|
||||||
|
in List.foldr (\x m -> Dict.update x succ m) Dict.empty ls
|
||||||
|
|
||||||
|
uniqSingleton : List Int -> Maybe Int
|
||||||
|
uniqSingleton ls = let cs = counts ls
|
||||||
|
in case Dict.toList cs of
|
||||||
|
[(n, 1), (m, 3)] -> Just n
|
||||||
|
[(n, 3), (m, 1)] -> Just m
|
||||||
|
[(1, 2), (2, 2)] -> Just 3
|
||||||
|
[(1, 2), (3, 2)] -> Just 2
|
||||||
|
[(2, 2), (3, 2)] -> Just 1
|
||||||
|
_ -> Nothing
|
||||||
|
|
||||||
|
getNBOutputs : World -> Maybe Int
|
||||||
|
getNBOutputs grid = grid
|
||||||
|
|> getNeighbours
|
||||||
|
|> List.filterMap identity
|
||||||
|
|> uniqSingleton
|
||||||
|
--|> List.map output
|
||||||
|
--|> List.map2 (\x y -> x * y) [2,2,1,0]
|
||||||
|
--|> List.sum
|
||||||
|
--|> \x -> 1 + x % inputs
|
||||||
|
|
||||||
|
step2 : AutomatonT -> Maybe Int -> Maybe Int -> Maybe Int
|
||||||
|
step2 aut s i = case i of
|
||||||
|
Nothing -> s
|
||||||
|
Just i2 -> Automaton.step aut s i2
|
||||||
|
|
||||||
cellStep : AutomatonT -> World -> Maybe Int
|
cellStep : AutomatonT -> World -> Maybe Int
|
||||||
cellStep aut grid = let
|
cellStep aut grid = let
|
||||||
i = getNBOutputs grid
|
i = getNBOutputs grid
|
||||||
s = grid |> Grid.extract
|
s = extract grid
|
||||||
t = Automaton.step aut s i
|
t = step2 aut s i
|
||||||
in t
|
in t
|
||||||
|
|
||||||
update : Msg -> Model -> (Model, Cmd Msg)
|
update : Msg -> Model -> (Model, Cmd Msg)
|
||||||
|
@ -79,7 +108,8 @@ update msg model =
|
||||||
Update grid -> ({ model | grid = grid }, Cmd.none)
|
Update grid -> ({ model | grid = grid }, Cmd.none)
|
||||||
NewRandomAut aut -> ({ model | system = aut }, Cmd.none)
|
NewRandomAut aut -> ({ model | system = aut }, Cmd.none)
|
||||||
Regen -> (model, Random.generate NewRandomAut (genAut states inputs))
|
Regen -> (model, Random.generate NewRandomAut (genAut states inputs))
|
||||||
BigStep -> ({ model | grid = Grid.extend (cellStep model.system) model.grid }, Cmd.none)
|
BigStep -> ({ model | grid = model.grid =>> cellStep model.system }, Cmd.none)
|
||||||
|
Init -> ({ model | grid = generate width height initCell }, Cmd.none)
|
||||||
|
|
||||||
|
|
||||||
-- SUBSCRIPTIONS
|
-- SUBSCRIPTIONS
|
||||||
|
@ -93,19 +123,18 @@ subscriptions model = Time.every freq (\a -> BigStep)
|
||||||
(=>) = (,)
|
(=>) = (,)
|
||||||
|
|
||||||
output2Color : Int -> Color
|
output2Color : Int -> Color
|
||||||
output2Color n = hsl (degrees (toFloat n)*77) 1.0 (0.8 - 0.6 * (toFloat n + 0.5)/outputs)
|
output2Color n = Color.hsl (degrees (toFloat n)*77) 1.0 (0.8 - 0.6 * (toFloat n + 0.5)/outputs)
|
||||||
|
|
||||||
color2String : Color -> String
|
color2String : Color -> String
|
||||||
color2String c = let rgb = toRgb c in "rgb(" ++ toString rgb.red ++ ", " ++ toString rgb.green ++ ", " ++ toString rgb.blue ++ ")"
|
color2String c = let rgb = Color.toRgb c in "rgb(" ++ toString rgb.red ++ ", " ++ toString rgb.green ++ ", " ++ toString rgb.blue ++ ")"
|
||||||
|
|
||||||
block aut grid = let
|
block aut grid = let
|
||||||
col = output2Color <| output <| Grid.extract grid
|
col = output2Color <| output <| extract grid
|
||||||
but = text "" -- button [ onClick (Update (Grid.edit (\_ -> cellStep aut grid) grid)) ] [ text "." ]
|
but = text "" -- button [ onClick (Update (Grid.edit (\_ -> cellStep aut grid) grid)) ] [ text "." ]
|
||||||
in div [style ["background-color" => color2String col, "width" => visSize, "height" => visSize, "display" => "inline-block"]] [ but ]
|
in div [style ["background-color" => color2String col, "width" => visSize, "height" => visSize, "display" => "inline-block"]] [ but ]
|
||||||
|
|
||||||
view model = let
|
view model = let
|
||||||
dupmodel = Grid.duplicate model.grid
|
butts = model.grid =>> block model.system
|
||||||
butts = Grid.map (block model.system) dupmodel
|
|
||||||
listm = Grid.toList butts
|
listm = Grid.toList butts
|
||||||
viewm = List.map (\row -> div [style ["height" => visSize]] row) listm
|
viewm = List.map (\row -> div [style ["height" => visSize]] row) listm
|
||||||
in div [] <| viewm ++ [button [onClick BigStep] [text "big step"], button [onClick Regen] [text "regenerate"]]
|
in div [] <| viewm ++ [button [onClick BigStep] [text "big step"], button [onClick Regen] [text "regenerate"], button [onClick Init] [text "restart"]]
|
||||||
|
|
58
RingList.elm
58
RingList.elm
|
@ -1,58 +0,0 @@
|
||||||
module RingList exposing (..)
|
|
||||||
|
|
||||||
type alias RingList a =
|
|
||||||
{ before : List a
|
|
||||||
, focus : a
|
|
||||||
, after : List a
|
|
||||||
}
|
|
||||||
|
|
||||||
{- Basic conversion -}
|
|
||||||
fromList : a -> List a -> RingList a
|
|
||||||
fromList a l = RingList [] a l
|
|
||||||
|
|
||||||
toList : RingList a -> List a
|
|
||||||
toList rl = List.reverse rl.before ++ [rl.focus] ++ rl.after
|
|
||||||
|
|
||||||
{- Functor like things -}
|
|
||||||
map : (a -> b) -> RingList a -> RingList b
|
|
||||||
map f rl = RingList (List.map f rl.before) (f rl.focus) (List.map f rl.after)
|
|
||||||
|
|
||||||
edit : (a -> a) -> RingList a -> RingList a
|
|
||||||
edit f rl = RingList rl.before (rl.focus |> f) rl.after
|
|
||||||
|
|
||||||
{- Comonad functions -}
|
|
||||||
extract : RingList a -> a
|
|
||||||
extract rl = rl.focus
|
|
||||||
|
|
||||||
duplicate : RingList a -> RingList (RingList a)
|
|
||||||
duplicate rl = let
|
|
||||||
lefts = iterate1N (List.length rl.before) shiftRight rl
|
|
||||||
rights = iterate1N (List.length rl.after) shiftLeft rl
|
|
||||||
in RingList lefts rl rights
|
|
||||||
|
|
||||||
extend : (RingList a -> b) -> RingList a -> RingList b
|
|
||||||
extend f w = map f (duplicate w)
|
|
||||||
|
|
||||||
(=>>) : RingList a -> (RingList a -> b) -> RingList b
|
|
||||||
(=>>) = flip extend
|
|
||||||
|
|
||||||
{- Domain functions -}
|
|
||||||
shiftLeft : RingList a -> RingList a
|
|
||||||
shiftLeft rl = case rl.after of
|
|
||||||
[] -> case List.reverse rl.before of
|
|
||||||
[] -> RingList [] rl.focus []
|
|
||||||
x::xs -> RingList [rl.focus] x xs
|
|
||||||
x::xs -> RingList (rl.focus :: rl.before) x xs
|
|
||||||
|
|
||||||
shiftRight : RingList a -> RingList a
|
|
||||||
shiftRight rl = case rl.before of
|
|
||||||
[] -> case List.reverse rl.after of
|
|
||||||
[] -> RingList [] rl.focus []
|
|
||||||
x::xs -> RingList xs x [rl.focus]
|
|
||||||
x::xs -> RingList xs x (rl.focus :: rl.after)
|
|
||||||
|
|
||||||
{- From here we have private functions -}
|
|
||||||
iterate1N : Int -> (a -> a) -> a -> List a
|
|
||||||
iterate1N n f a = case n of
|
|
||||||
0 -> []
|
|
||||||
m -> f a :: List.map f (iterate1N (m - 1) f a)
|
|
56
Test.elm
Normal file
56
Test.elm
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import Zipper exposing (..)
|
||||||
|
|
||||||
|
import Color exposing (Color)
|
||||||
|
import Dict exposing (Dict)
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.App as App
|
||||||
|
import Html.Attributes exposing (style)
|
||||||
|
import Html.Events exposing (onClick)
|
||||||
|
import Random
|
||||||
|
import Time
|
||||||
|
|
||||||
|
main =
|
||||||
|
App.program
|
||||||
|
{ init = init
|
||||||
|
, view = view
|
||||||
|
, update = update
|
||||||
|
, subscriptions = subscriptions
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 1000
|
||||||
|
|
||||||
|
-- MODEL
|
||||||
|
|
||||||
|
type alias Model = Zipper Int
|
||||||
|
|
||||||
|
init : (Model, Cmd Msg)
|
||||||
|
init = (fromList 0 [1..size], Cmd.none)
|
||||||
|
|
||||||
|
|
||||||
|
-- UPDATE
|
||||||
|
|
||||||
|
type Msg = Update (Zipper Int)
|
||||||
|
|
||||||
|
succ n = n + 1
|
||||||
|
|
||||||
|
update : Msg -> Model -> (Model, Cmd Msg)
|
||||||
|
update msg model =
|
||||||
|
case msg of
|
||||||
|
Update grid -> (edit succ grid, Cmd.none)
|
||||||
|
|
||||||
|
|
||||||
|
-- SUBSCRIPTIONS
|
||||||
|
|
||||||
|
subscriptions : Model -> Sub Msg
|
||||||
|
subscriptions model = Sub.none
|
||||||
|
|
||||||
|
|
||||||
|
-- VIEW
|
||||||
|
|
||||||
|
buttonView : Zipper Int -> Html Msg
|
||||||
|
buttonView zppr = button [onClick (Update zppr)] [text <| toString <| extract zppr]
|
||||||
|
|
||||||
|
view model = let
|
||||||
|
butts = model =>> buttonView
|
||||||
|
listm = List.intersperse (br [] []) (toList butts)
|
||||||
|
in div [] listm
|
58
Zipper.elm
Normal file
58
Zipper.elm
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
module Zipper exposing (..)
|
||||||
|
|
||||||
|
type alias Zipper a =
|
||||||
|
{ before : List a
|
||||||
|
, focus : a
|
||||||
|
, after : List a
|
||||||
|
}
|
||||||
|
|
||||||
|
{- Basic conversion -}
|
||||||
|
fromList : a -> List a -> Zipper a
|
||||||
|
fromList a l = Zipper [] a l
|
||||||
|
|
||||||
|
toList : Zipper a -> List a
|
||||||
|
toList rl = List.reverse rl.before ++ [rl.focus] ++ rl.after
|
||||||
|
|
||||||
|
{- Functor like things -}
|
||||||
|
map : (a -> b) -> Zipper a -> Zipper b
|
||||||
|
map f rl = Zipper (List.map f rl.before) (f rl.focus) (List.map f rl.after)
|
||||||
|
|
||||||
|
edit : (a -> a) -> Zipper a -> Zipper a
|
||||||
|
edit f rl = Zipper rl.before (rl.focus |> f) rl.after
|
||||||
|
|
||||||
|
{- Comonad functions -}
|
||||||
|
extract : Zipper a -> a
|
||||||
|
extract rl = rl.focus
|
||||||
|
|
||||||
|
duplicate : Zipper a -> Zipper (Zipper a)
|
||||||
|
duplicate rl = let
|
||||||
|
lefts = iterate1N (List.length rl.before) shiftRight rl
|
||||||
|
rights = iterate1N (List.length rl.after) shiftLeft rl
|
||||||
|
in Zipper lefts rl rights
|
||||||
|
|
||||||
|
extend : (Zipper a -> b) -> Zipper a -> Zipper b
|
||||||
|
extend f w = map f (duplicate w)
|
||||||
|
|
||||||
|
(=>>) : Zipper a -> (Zipper a -> b) -> Zipper b
|
||||||
|
(=>>) = flip extend
|
||||||
|
|
||||||
|
{- Domain functions -}
|
||||||
|
shiftLeft : Zipper a -> Zipper a
|
||||||
|
shiftLeft rl = case rl.after of
|
||||||
|
[] -> case List.reverse rl.before of
|
||||||
|
[] -> Zipper [] rl.focus []
|
||||||
|
x::xs -> Zipper [rl.focus] x xs
|
||||||
|
x::xs -> Zipper (rl.focus :: rl.before) x xs
|
||||||
|
|
||||||
|
shiftRight : Zipper a -> Zipper a
|
||||||
|
shiftRight rl = case rl.before of
|
||||||
|
[] -> case List.reverse rl.after of
|
||||||
|
[] -> Zipper [] rl.focus []
|
||||||
|
x::xs -> Zipper xs x [rl.focus]
|
||||||
|
x::xs -> Zipper xs x (rl.focus :: rl.after)
|
||||||
|
|
||||||
|
{- From here we have private functions -}
|
||||||
|
iterate1N : Int -> (a -> a) -> a -> List a
|
||||||
|
iterate1N n f a = case n of
|
||||||
|
0 -> []
|
||||||
|
m -> f a :: List.map f (iterate1N (m - 1) f a)
|
|
@ -8,8 +8,10 @@
|
||||||
],
|
],
|
||||||
"exposed-modules": [],
|
"exposed-modules": [],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"elm-community/elm-lazy-list": "1.3.0 <= v < 2.0.0",
|
||||||
"elm-lang/core": "4.0.5 <= v < 5.0.0",
|
"elm-lang/core": "4.0.5 <= v < 5.0.0",
|
||||||
"elm-lang/html": "1.1.0 <= v < 2.0.0"
|
"elm-lang/html": "1.1.0 <= v < 2.0.0",
|
||||||
|
"elm-lang/lazy": "1.0.0 <= v < 2.0.0"
|
||||||
},
|
},
|
||||||
"elm-version": "0.17.1 <= v < 0.18.0"
|
"elm-version": "0.17.1 <= v < 0.18.0"
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue