Skip to content

Commit 8668d1c

Browse files
committed
Switch to StateT
1 parent ff6d0eb commit 8668d1c

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,11 +171,11 @@ 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
/// Run the parser, if it fails swap the error message.
200177
let inline ( <??> ) (parser : ParserMonad<'a>) (genMessage : Pos -> string) : ParserMonad<'a> =
201-
ParserMonad <| fun st ->
178+
StateT <| fun st ->
202179
match apply1 parser st with
203180
| Ok result -> Ok result
204181
| Error e ->
@@ -240,16 +217,16 @@ module ParserMonad =
240217

241218

242219
let fatalError err =
243-
ParserMonad <| fun st -> Error (mkParseError st err)
220+
StateT <| fun st -> Error (mkParseError st err)
244221

245222
let getRunningEvent : ParserMonad<VoiceEvent> =
246-
ParserMonad <| fun st -> Ok (st.RunningStatus , st)
223+
StateT <| fun st -> Ok (st.RunningStatus , st)
247224

248225
let inline setRunningEvent (runningStatus : VoiceEvent) : ParserMonad<unit> =
249-
ParserMonad <| fun st -> Ok ((), { st with RunningStatus = runningStatus })
226+
StateT <| fun st -> Ok ((), { st with RunningStatus = runningStatus })
250227

251228
let getPos : ParserMonad<int> =
252-
ParserMonad <| fun st -> Ok (st.Position, st)
229+
StateT <| fun st -> Ok (st.Position, st)
253230

254231
let inline private (|PositionValid|PositionInvalid|) (input: MidiData, state: State) =
255232
if state.Position >= 0 && state.Position < input.Length then
@@ -258,7 +235,7 @@ module ParserMonad =
258235
PositionInvalid
259236

260237
let inline private checkedParseM (name: string) (f: State -> Result<('a * State), ParseError>) =
261-
ParserMonad
238+
StateT
262239
(fun state ->
263240
try
264241
match state.Input, state with
@@ -286,7 +263,7 @@ module ParserMonad =
286263
/// Repeats a given <see paramref="parser"/> <see paramref="length"/> times.
287264
/// Fails with accumulated errors when any encountered.
288265
let inline count (length : ^T) (parser : ParserMonad<'a>) : ParserMonad<'a []> =
289-
ParserMonad <| fun state ->
266+
StateT <| fun state ->
290267
let rec work (i : 'T)
291268
(st : State)
292269
(fk : ParseError -> Result<'a list * State, ParseError>)
@@ -305,7 +282,7 @@ module ParserMonad =
305282

306283
/// Run a parser within a bounded section of the input stream.
307284
let repeatTillPosition (maxPosition: Pos) (p: ParserMonad<'a>) : ParserMonad<'a array> =
308-
ParserMonad(fun state ->
285+
StateT(fun state ->
309286
let results = ResizeArray()
310287
let mutable firstError = Ok (Array.empty, state)
311288
let mutable lastState = state
@@ -328,7 +305,7 @@ module ParserMonad =
328305
)
329306

330307
let inline boundRepeat (n: ^T) (p: ParserMonad<'a>) : ParserMonad<'a array> =
331-
ParserMonad(fun state ->
308+
StateT (fun state ->
332309
let result = Array.zeroCreate (int n)
333310
let mutable lastState = state
334311
// revisit with a fold?
@@ -426,4 +403,4 @@ module ParserMonad =
426403
let! b = readByte
427404
let! c = readByte
428405
return (word24be a b c)
429-
}
406+
}

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)