Skip to content

Commit 636445c

Browse files
committed
Switch to StateT
1 parent 1fc56d5 commit 636445c

File tree

2 files changed

+21
-43
lines changed

2 files changed

+21
-43
lines changed

src/ZMidi/Internal/ParserMonad.fs

Lines changed: 20 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ namespace ZMidi.Internal
44
module ParserMonad =
55

66
open System.IO
7-
7+
open FSharpPlus
8+
open FSharpPlus.Data
89
open ZMidi.Internal.Utils
910

1011
/// Status is either OFF or the previous VoiceEvent * Channel.
@@ -87,8 +88,7 @@ module ParserMonad =
8788
#endif
8889
)
8990

90-
type ParserMonad<'a> =
91-
ParserMonad of (State -> Result<'a * State, ParseError> )
91+
type ParserMonad<'a> = StateT<State, Result<'a * State, ParseError>>
9292

9393
let nullOut = new StreamWriter(Stream.Null) :> TextWriter
9494
let mutable debug = false
@@ -101,7 +101,7 @@ module ParserMonad =
101101

102102
let inline private apply1 (parser : ParserMonad<'a>)
103103
(state : State) : Result<'a * State, ParseError> =
104-
let (ParserMonad fn) = parser
104+
let (StateT fn) = parser
105105
try
106106
let result = fn state
107107
let oldState = state
@@ -131,20 +131,20 @@ module ParserMonad =
131131
)
132132

133133
let inline mreturn (x:'a) : ParserMonad<'a> =
134-
ParserMonad <| fun st -> Ok (x, st)
134+
StateT <| fun st -> Ok (x, st)
135135

136136
let inline private bindM (parser : ParserMonad<'a>)
137137
(next : 'a -> ParserMonad<'b>) : ParserMonad<'b> =
138-
ParserMonad <| fun state ->
138+
StateT <| fun state ->
139139
match apply1 parser state with
140140
| Error msg -> Error msg
141141
| Ok (ans, st1) -> apply1 (next ans) st1
142142

143143
let mzero () : ParserMonad<'a> =
144-
ParserMonad <| fun state -> Error (mkParseError state (EOF "mzero"))
144+
StateT <| fun state -> Error (mkParseError state (EOF "mzero"))
145145

146146
let inline mplus (parser1 : ParserMonad<'a>) (parser2 : ParserMonad<'a>) : ParserMonad<'a> =
147-
ParserMonad <| fun state ->
147+
StateT <| fun state ->
148148
match apply1 parser1 state with
149149
| Error _ -> apply1 parser2 state
150150
| Ok res -> Ok res
@@ -158,30 +158,7 @@ module ParserMonad =
158158
let (>>=) (m: ParserMonad<'a>) (k: 'a -> ParserMonad<'b>) : ParserMonad<'b> =
159159
bindM m k
160160

161-
type ParserBuilder() =
162-
member inline self.ReturnFrom (ma:ParserMonad<'a>) : ParserMonad<'a> = ma
163-
member inline self.Return x = mreturn x
164-
member inline self.Bind (p,f) = bindM p f
165-
member inline self.Zero a = ParserMonad (fun state -> Ok(a, state))
166-
//member self.Combine (ma, mb) = ma >>= mb
167-
168-
// inspired from http://www.fssnip.net/7UJ/title/ResultBuilder-Computational-Expression
169-
// probably broken
170-
member inline self.TryFinally(m, compensation) =
171-
try self.ReturnFrom(m)
172-
finally compensation()
173-
174-
//member self.Delay(f: unit -> ParserMonad<'a>) : ParserMonad<'a> = f ()
175-
//member self.Using(res:#System.IDisposable, body) =
176-
// self.TryFinally(body res, fun () -> if not (isNull res) then res.Dispose())
177-
//member self.While(guard, f) =
178-
// if not (guard()) then self.Zero () else
179-
// do f() |> ignore
180-
// self.While(guard, f)
181-
//member self.For(sequence:seq<_>, body) =
182-
// self.Using(sequence.GetEnumerator(), fun enum -> self.While(enum.MoveNext, fun () -> self.Delay(fun () -> body enum.Current)))
183-
184-
let (parseMidi:ParserBuilder) = new ParserBuilder()
161+
let parseMidi = monad
185162

186163
let runParser (ma:ParserMonad<'a>) input initialState =
187164
apply1 ma { initialState with Input = input}
@@ -194,10 +171,10 @@ module ParserMonad =
194171

195172
/// Throw a parse error
196173
let parseError (genMessage : Pos -> string) : ParserMonad<'a> =
197-
ParserMonad <| fun st -> Error (mkOtherParseError st genMessage)
174+
StateT <| fun st -> Error (mkOtherParseError st genMessage)
198175

199176
let fmapM (modify: 'a -> 'b) (parser : ParserMonad<'a>) : ParserMonad<'b> =
200-
ParserMonad <| fun state ->
177+
StateT <| fun state ->
201178
match apply1 parser state with
202179
| Error err -> Error err
203180
| Ok (a, st2) -> Ok (modify a, st2)
@@ -208,7 +185,7 @@ module ParserMonad =
208185

209186
/// Run the parser, if it fails swap the error message.
210187
let inline ( <??> ) (parser : ParserMonad<'a>) (genMessage : Pos -> string) : ParserMonad<'a> =
211-
ParserMonad <| fun st ->
188+
StateT <| fun st ->
212189
match apply1 parser st with
213190
| Ok result -> Ok result
214191
| Error e ->
@@ -250,16 +227,16 @@ module ParserMonad =
250227

251228

252229
let fatalError err =
253-
ParserMonad <| fun st -> Error (mkParseError st err)
230+
StateT <| fun st -> Error (mkParseError st err)
254231

255232
let getRunningEvent : ParserMonad<VoiceEvent> =
256-
ParserMonad <| fun st -> Ok (st.RunningStatus , st)
233+
StateT <| fun st -> Ok (st.RunningStatus , st)
257234

258235
let inline setRunningEvent (runningStatus : VoiceEvent) : ParserMonad<unit> =
259-
ParserMonad <| fun st -> Ok ((), { st with RunningStatus = runningStatus })
236+
StateT <| fun st -> Ok ((), { st with RunningStatus = runningStatus })
260237

261238
let getPos : ParserMonad<int> =
262-
ParserMonad <| fun st -> Ok (st.Position, st)
239+
StateT <| fun st -> Ok (st.Position, st)
263240

264241
let inline private (|PositionValid|PositionInvalid|) (input: MidiData, state: State) =
265242
if state.Position >= 0 && state.Position < input.Length then
@@ -268,7 +245,7 @@ module ParserMonad =
268245
PositionInvalid
269246

270247
let inline private checkedParseM (name: string) (f: State -> Result<('a * State), ParseError>) =
271-
ParserMonad
248+
StateT
272249
(fun state ->
273250
try
274251
match state.Input, state with
@@ -296,7 +273,7 @@ module ParserMonad =
296273
/// Repeats a given <see paramref="parser"/> <see paramref="length"/> times.
297274
/// Fails with accumulated errors when any encountered.
298275
let inline count (length : ^T) (parser : ParserMonad<'a>) : ParserMonad<'a []> =
299-
ParserMonad <| fun state ->
276+
StateT <| fun state ->
300277
let rec work (i : 'T)
301278
(st : State)
302279
(fk : ParseError -> Result<'a list * State, ParseError>)
@@ -314,7 +291,7 @@ module ParserMonad =
314291

315292
/// Run a parser within a bounded section of the input stream.
316293
let repeatTillPosition (maxPosition: Pos) (parser: ParserMonad<'a>) : ParserMonad<'a array> =
317-
ParserMonad <| fun state ->
294+
StateT <| fun state ->
318295
let limit = maxPosition
319296
let rec work (st : State)
320297
(fk : ParseError -> Result<'a list * State, ParseError>)
@@ -402,4 +379,4 @@ module ParserMonad =
402379
let! b = readByte
403380
let! c = readByte
404381
return (word24be a b c)
405-
}
382+
}

src/ZMidi/Read.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace ZMidi
22

3+
open FSharpPlus
34
open ZMidi.DataTypes
45

56
module ReadFile =

0 commit comments

Comments
 (0)