Browse Source

Did a lot. Not sure it compiles. Tried Laziness

master
Joshua Moerman 8 years ago
parent
commit
d6ea01b330
  1. 25
      Automaton.elm
  2. 38
      Grid.elm
  3. 65
      Lazy/Zipper.elm
  4. 87
      Main.elm
  5. 58
      RingList.elm
  6. 56
      Test.elm
  7. 58
      Zipper.elm
  8. 4
      elm-package.json

25
Automaton.elm

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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)

4
elm-package.json

@ -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"
} }