Created
August 12, 2016 13:55
-
-
Save newlandsvalley/733ced7c86b738732028b4480e83980e to your computer and use it in GitHub Desktop.
elm-check Producers and recursive data structures
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Checks exposing (..) | |
import Producers exposing (..) | |
import Mus exposing (..) | |
import Check exposing (..) | |
import Check.Producer exposing (..) | |
import Check.Test | |
import ElmTest | |
-- Tests for Music | |
claim_retro_retains_duration = | |
claim | |
"a line of music reversed retains its duration" | |
`that` | |
(\m -> duration (retro m)) | |
`is` | |
(\m -> duration m) | |
`for` | |
music | |
suite_music = | |
suite "Music Suite" | |
[ | |
claim_retro_retains_duration | |
] | |
evidence : Evidence | |
evidence = quickCheck suite_music | |
main = | |
ElmTest.runSuite (Check.Test.evidenceToTest evidence) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Mus exposing (..) | |
{-| | |
@docs Music, duration, retro | |
-} | |
import Basics exposing (max) | |
{-| a reduced form of HSoM's Music data type -} | |
type Music = | |
Note Int | |
| Rest Int | |
| Seq Music Music | |
| Par Music Music | |
{-| a reduced form of a function to get the duration of a piece of music -} | |
duration : Music -> Int | |
duration m = | |
case m of | |
Note i -> | |
i | |
Rest i -> | |
i | |
Seq a b -> | |
(duration a) + (duration b) | |
Par a b -> | |
max (duration a) (duration b) | |
{-| a retrogade piece -} | |
retro : Music -> Music | |
retro m = | |
case m of | |
Note _ -> | |
m | |
Rest _ -> | |
m | |
Seq m1 m2 -> | |
Seq (retro m2) (retro m1) | |
Par m1 m2 -> | |
let d1 = duration m1 | |
d2 = duration m2 | |
in | |
if (d1 == d2) then | |
Par (retro m2) (retro m1) | |
else if (d1 > d2) then | |
Par (retro m1) (Seq (Rest (d1 - d2)) (retro m2)) | |
else | |
Par (Seq (Rest (d2 - d1)) (retro m1)) (retro m2) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Producers exposing (..) | |
import Random exposing (Generator) | |
import Check.Producer exposing (..) | |
import Random.Extra exposing (..) | |
import Mus exposing (..) | |
import Debug exposing (..) | |
{-| a producer for a single note -} | |
note : Producer Music | |
note = | |
rangeInt 1 8 | |
|> Check.Producer.map Note | |
{-| a producer for a single rest -} | |
rest : Producer Music | |
rest = | |
rangeInt 1 8 | |
|> Check.Producer.map Rest | |
{-| a sequential or parallel production of music -} | |
parseq : (Music -> Music -> Music) -> Producer Music | |
parseq constructor = | |
let | |
{- replace the line below with | |
pair = Check.Producer.tuple (note, note) | |
and the runtime doesn't crash | |
-} | |
pair = Check.Producer.tuple (music, music) | |
_ = log "parseq" pair | |
in | |
pair | |
|> Check.Producer.map (\(a,b) -> constructor a b) | |
{-| music -} | |
music : Producer Music | |
music = | |
let | |
generator = | |
choices | |
[ note.generator | |
, rest.generator | |
, (parseq Seq).generator | |
, (parseq Par).generator | |
] | |
shrinker pr = | |
case pr of | |
Note _ -> note.shrinker pr | |
Rest _ -> rest.shrinker pr | |
Seq _ _ -> (parseq Seq).shrinker pr | |
Par _ _ -> (parseq Par).shrinker pr | |
in | |
Producer generator shrinker | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm trying to learn how to write an elm-check Producer for a recursive data structure. The Music data type refers to itself in its constructors. The parseq function in Producers.elm (as written) is intended to build Music trees of arbitrary depth. However, the check crashes at run time with the error
If I prevent recursive generation by replacing the line
with the non-recursive
then the check runs (albeit with limited data)