I am redesigning the library and am not comfortable with the current design template. This question is about using a strategic template in conjunction with a state monad.
I have a Filter . All he does in his main implementation is to take some data file of type 'd and the update itself, creating a new updated copy of itself.
[<AbstractClass>] type Filter<'d, 'F> (state: 'F) = member val StateVariable = state with get abstract member Update: 'd -> Filter<'d, 'F>
I have a ISignalGenerator that takes a filter, environmental data and processes it to generate a Signal type 'S
type ISignalGenerator<'d, 'F, 'S> = abstract member GenerateSignal: 'd -> Filter<'d,'F> -> 'S
SignalGenerator is an object of the strategy template. In SignalGenerator implementations, the SignalGenerator user mounts the functions that will be used and combined to generate Signal .
I could wrap my code in state monad. Along with some environment variables (datafeed), the state monad will carry the Filter filter as a state. SignalGenerator will receive state updates through the state monad (data type 'd and Filter data)
The design problem I have is that I would like to separate the SignalGenerator type from the workflow development, i.e. I would like to avoid embedding the state monad in the stomach of SignalGenerator . Is there a functional design diagram for this?
EDIT
Based on Thomas's comment, I worked on a toy model. The choice of a strategy class is based on the need to combine several functions.
///////////////////////////////////////////////////////////////////////////////////// // Definition of the state ///////////////////////////////////////////////////////////////////////////////////// type StateFunc<'State, 'T> = 'State -> 'T * 'State ///////////////////////////////////////////////////////////////////////////////////// // Definition of the State monad type ///////////////////////////////////////////////////////////////////////////////////// type StateMonadBuilder<'State>() = // M<'T> -> M<'T> member b.ReturnFrom a : StateFunc<'State, 'T> = a // 'T -> M<'T> member b.Return a : StateFunc<'State, 'T> = ( fun s -> a, s) // M<'T> * ('T -> M<'U>) -> M<'U> member b.Bind(p : StateFunc<_, 'T>, rest : 'T -> StateFunc<_,_>) : StateFunc<'State, 'U> = (fun s -> let a, s' = ps rest a s') // Getter for the whole state, this type signature is because it passes along the state & returns the state member b.getState : StateFunc<'State, _> = (fun s -> s, s) // Setter for the state member b.putState (s:'State) : StateFunc<'State, _> = (fun _ -> (), s) ///////////////////////////////////////////////////////////////////////////////////// // The actual example ///////////////////////////////////////////////////////////////////////////////////// let state = StateMonadBuilder<int> () // DoubleFunctOne defines standard operations that remain always the same type Strategy (functOne) = member this.DoubleFunctOne (x: int) = state { let! res = functOne x return res * 2 } // I introduce customization with the definition of this function. // Whenever I need, I will swap the function with some other let myFunctOne x = state { let someOtherFun x = x + 10 let! currState = state.getState return currState * someOtherFun x} // Here I mount the custom function on the strategy class, so the Strategy.DoubleFunctOne can produce a result // In order to do so, I need to keep the construction in the state monad let strategy1 = state { return Strategy (myFunctOne) } // Here begins the client side. The client will consume the methods provided by my strategies. // He should not be concerned by the construction of the strategies // Ok, then, let put our work in production let test1 = (state { let! strategy = strategy1 return! strategy.DoubleFunctOne 10 }) 9
I was wondering if there would be a template solution in which the Strategy class could use the established functions without inserting the state monad in the stomach. In other words, is there a way to defer the definition of let state = StateMonadBuilder<int> () without landing in a type-type headache?
I am relatively new to functional programming and F #. Please let me know if my question even makes sense! Thanks.