From c5a22cb9f2bd46926b614d9c469bebc63ba4b30b Mon Sep 17 00:00:00 2001
From: Gustavo Leon <1261319+gusty@users.noreply.github.com>
Date: Fri, 31 Jan 2020 09:39:41 +0100
Subject: [PATCH 1/2] Include F#
---
src/ZMidi/zmidi-fs-core.fsproj | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/ZMidi/zmidi-fs-core.fsproj b/src/ZMidi/zmidi-fs-core.fsproj
index 7e58909..eb59bb0 100644
--- a/src/ZMidi/zmidi-fs-core.fsproj
+++ b/src/ZMidi/zmidi-fs-core.fsproj
@@ -21,4 +21,8 @@
+
+
+
+
From 19ddde9d752296bb2d5e15b5bdb786534fb97ae5 Mon Sep 17 00:00:00 2001
From: Gusty <1261319+gusty@users.noreply.github.com>
Date: Sun, 2 Feb 2020 20:18:10 +0100
Subject: [PATCH 2/2] Switch to ReaderT
---
src/ZMidi/Internal/ParserMonad.fs | 42 ++++++++-----------------------
src/ZMidi/Read.fs | 2 +-
2 files changed, 11 insertions(+), 33 deletions(-)
diff --git a/src/ZMidi/Internal/ParserMonad.fs b/src/ZMidi/Internal/ParserMonad.fs
index 4f32686..47f65a2 100755
--- a/src/ZMidi/Internal/ParserMonad.fs
+++ b/src/ZMidi/Internal/ParserMonad.fs
@@ -4,7 +4,8 @@ namespace ZMidi.Internal
module ParserMonad =
open System.IO
-
+ open FSharpPlus
+ open FSharpPlus.Data
open ZMidi.Internal.Utils
/// Status is either OFF or the previous VoiceEvent * Channel.
@@ -85,8 +86,7 @@ module ParserMonad =
#endif
)
- type ParserMonad<'a> =
- ParserMonad of (MidiData -> State -> Result<'a * State, ParseError> )
+ type ParserMonad<'a> = ReaderT>>
let nullOut = new StreamWriter(Stream.Null) :> TextWriter
let mutable debug = false
@@ -100,7 +100,7 @@ module ParserMonad =
let inline private apply1 (parser : ParserMonad<'a>)
(midiData : byte[])
(state : State) : Result<'a * State, ParseError> =
- let (ParserMonad fn) = parser
+ let fn = ReaderT.run parser >> StateT.run
try
let result = fn midiData state
let oldState = state
@@ -129,8 +129,9 @@ module ParserMonad =
)
)
+ let ParserMonad f = ReaderT (fun r -> StateT (fun s -> f r s))
let inline mreturn (x:'a) : ParserMonad<'a> =
- ParserMonad <| fun _ st -> Ok (x, st)
+ ReaderT <| fun _ -> StateT (fun st -> Ok (x, st))
let inline private bindM (parser : ParserMonad<'a>)
(next : 'a -> ParserMonad<'b>) : ParserMonad<'b> =
@@ -156,31 +157,8 @@ module ParserMonad =
let (>>=) (m: ParserMonad<'a>) (k: 'a -> ParserMonad<'b>) : ParserMonad<'b> =
bindM m k
-
- type ParserBuilder() =
- member inline self.ReturnFrom (ma:ParserMonad<'a>) : ParserMonad<'a> = ma
- member inline self.Return x = mreturn x
- member inline self.Bind (p,f) = bindM p f
- member inline self.Zero a = ParserMonad (fun input state -> Ok(a, state))
- //member self.Combine (ma, mb) = ma >>= mb
-
- // inspired from http://www.fssnip.net/7UJ/title/ResultBuilder-Computational-Expression
- // probably broken
- member inline self.TryFinally(m, compensation) =
- try self.ReturnFrom(m)
- finally compensation()
-
- //member self.Delay(f: unit -> ParserMonad<'a>) : ParserMonad<'a> = f ()
- //member self.Using(res:#System.IDisposable, body) =
- // self.TryFinally(body res, fun () -> if not (isNull res) then res.Dispose())
- //member self.While(guard, f) =
- // if not (guard()) then self.Zero () else
- // do f() |> ignore
- // self.While(guard, f)
- //member self.For(sequence:seq<_>, body) =
- // self.Using(sequence.GetEnumerator(), fun enum -> self.While(enum.MoveNext, fun () -> self.Delay(fun () -> body enum.Current)))
-
- let (parseMidi:ParserBuilder) = new ParserBuilder()
+
+ let parseMidi = monad
let runParser (ma:ParserMonad<'a>) input initialState =
apply1 ma input initialState
@@ -385,7 +363,7 @@ module ParserMonad =
?> sprintf "word14be: failed at %i"
/// Parse a word32 (big endian).
- let readUInt32be =
+ let readUInt32be : ParserMonad<_> =
parseMidi {
let! a = readByte
let! b = readByte
@@ -395,7 +373,7 @@ module ParserMonad =
}
/// Parse a word24 (big endian).
- let readWord24be =
+ let readWord24be : ParserMonad<_> =
parseMidi {
let! a = readByte
let! b = readByte
diff --git a/src/ZMidi/Read.fs b/src/ZMidi/Read.fs
index 8b6c8ad..b824afa 100644
--- a/src/ZMidi/Read.fs
+++ b/src/ZMidi/Read.fs
@@ -186,7 +186,7 @@ module ReadFile =
|> function | Some i -> true
| None -> false
- let rec sysExContPackets =
+ let rec sysExContPackets : ParserMonad<_> =
parseMidi {
let! d = deltaTime
let! b = getVarlenBytes