Монада состояния и шаблон стратегии

Я переделываю библиотеку, и меня не устраивает текущий шаблон проектирования. Этот вопрос касается использования шаблона стратегии в сочетании с Монада состояния

У меня есть Filter. Все, что он делает в своей базовой реализации, это берет некоторый поток данных типа 'd и обновляет себя, создавая новую обновленную копию самого себя.

[<AbstractClass>]
type Filter<'d, 'F> (state: 'F) =
    member val StateVariable = state with get
    abstract member Update: 'd -> Filter<'d, 'F>

Затем у меня есть ISignalGenerator, который берет фильтр, данные об окружающей среде и обрабатывает их для создания Signal типа 'S.

type ISignalGenerator<'d, 'F, 'S> =
    abstract member GenerateSignal: 'd -> Filter<'d,'F> -> 'S

SignalGenerator — это объект шаблона стратегии. В реализациях SignalGenerator пользователь библиотеки монтирует функции, которые будут использоваться и комбинироваться для создания файла Signal.

Я мог бы обернуть свой код в монаду состояния. Вместе с некоторыми переменными окружения (потоком данных) монада состояния будет нести «Фильтр» как состояние. Затем SignalGenerator будет получать обновления состояния через монаду состояния (поток данных типа 'd и Filter).

Проблема дизайна, с которой я столкнулся, заключается в том, что я хотел бы отделить тип SignalGenerator от разработки рабочего процесса, то есть я хотел бы избежать вложения монады состояния в чрево SignalGenerator. Существует ли функциональный шаблон проектирования для достижения этой цели?

ИЗМЕНИТЬ

Основываясь на комментарии Томаса, я работал над игрушечной моделью. Выбор наличия класса стратегии основан на необходимости объединить ряд функций.

/////////////////////////////////////////////////////////////////////////////////////
// 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' = p s
            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's put our work in production
let test1 = (state {
    let! strategy = strategy1
    return! strategy.DoubleFunctOne 10 }) 9

Мне было интересно, будет ли решение шаблона, в котором класс Strategy мог бы использовать смонтированные функции, не вложив монаду состояния в свое чрево. Другими словами, есть ли способ отложить определение let state = StateMonadBuilder<int> (), не прибегая к головной боли при выводе типов?

Я относительно новичок в функциональном программировании и F#. Пожалуйста, дайте мне знать, если мой вопрос имеет смысл! Спасибо.


person NoIdeaHowToFixThis    schedule 27.11.2013    source источник
comment
На этот вопрос сложно ответить, потому что он говорит о деталях вашего дизайна, не объясняя, в чем заключается проблема высокого уровня. Я думаю, что если вы объясните, как вы пришли к дизайну, который у вас есть в настоящее время, люди смогут дать вам более полезные ответы. (Другими словами, я понятия не имею, что вы пытаетесь здесь сделать...)   -  person Tomas Petricek    schedule 27.11.2013
comment
Этот XY-questions-post поможет вам чтобы улучшить свой вопрос.   -  person ekostadinov    schedule 09.10.2014
comment
Я попробовал это с let state = StateMonad<_>(), и остальная часть примера сработала. Я также мог бы пропустить все другие аннотации типов и просто позволить выводу типов делать свою работу. Это то, что ты имеешь в виду?   -  person halcwb    schedule 09.06.2016
comment
Мне непонятно, зачем здесь нужна или полезна монада состояния. Почему нельзя просто передать функцию в качестве аргумента?   -  person VoronoiPotato    schedule 06.08.2019