0

Trying to write a simplistic "model-view-controller" app in Haskell (just to learn):

Given the general types TState TAction TReaction, the key definition is that the function for change the model is

(TAction, TState) -> (TReaction, TState) (:: TFunction_ChangeModel)

The code to create a function :: TFunction_ChangeModel or a function :: TFunction_ModelAndViewCombined is fixed and can be easily generalized (when the necessary functions are provided, see the program below).

I would like (this is the question) to get rid of having to define dummy types like type TState = Int with a note 'please customize'.

Thus,

can the following code be written without the first three type Txxxx = ?

(Note: any suggestion and criticism is welcome).

-- just to make this compile
type TState = Int
type TAction = Char
type TReaction = Double

-- aply an action to an state gives a new state
type TFunction_ChangeState = TState -> TAction -> TState 

-- when a state is entered, a reaction is produced
type TFunction_WhatReaction = TState -> TReaction

-- the model is a function  from an action and a state into a new state and a reaction
type TFunction_ChangeModel =  (TAction, TState) -> (TReaction, TState)

-- given the functions for changing state and finding out what reaction is produced
-- it is straightforward to define the function for change a model
createModelChangeFunction :: TFunction_ChangeState -> TFunction_WhatReaction -> TFunction_ChangeModel
createModelChangeFunction changeState whatReaction = \(ac, st) -> let
        ns = changeState  st ac
        re = whatReaction ns
        in (re, ns)

-- show a view of a transition to a new state and the associated reaction
type TFunction_View = (TReaction, TState) -> IO ()

-- change model and view functions can be easily combined
type TFunction_ModelAndViewCombined = (TAction, TState) -> IO TState

combineModelAndView :: TFunction_ChangeModel -> TFunction_View -> TFunction_ModelAndViewCombined
combineModelAndView change view = \(a, s) -> do
                   let (r, s') = change (a, s)
                   view (r, s')
                   return s'

--
type TFunction_ControllerLoop = TState -> TFunction_ModelAndViewCombined -> IO TState

--
main = do
     print "hi"
Erik Kaplun
  • 33,421
  • 12
  • 92
  • 102
cibercitizen1
  • 19,104
  • 14
  • 65
  • 90

2 Answers2

2

not sure what you are trying to do here - but if you just want to parametrize over the state, action, reaction... then you can lift those as type-paramters in your types:

-- aply an action to an state gives a new state
type TFunction_ChangeState tState tAction = tState -> tAction -> tState 

-- when a state is entered, a reaction is produced
type TFunction_WhatReaction tState tReaction = tState -> tReaction

-- the model is a function  from an action and a state into a new state and a reaction
type TFunction_ChangeModel tState tAction tReaction =  (tAction, tState) -> (tReaction, tState)

-- given the functions for changing state and finding out what reaction is produced
-- it is straightforward to define the function for change a model
createModelChangeFunction :: TFunction_ChangeState tState tAction
                           -> TFunction_WhatReaction tState tReaction
                           -> TFunction_ChangeModel tState tAction tReaction
createModelChangeFunction changeState whatReaction = \(ac, st) -> let
        ns = changeState  st ac
        re = whatReaction ns
        in (re, ns)

-- show a view of a transition to a new state and the associated reaction
type TFunction_View tState tReaction = (tReaction, tState) -> IO ()

-- change model and view functions can be easily combined
type TFunction_ModelAndViewCombined tState tAction = (tAction, tState) -> IO tState

combineModelAndView :: TFunction_ChangeModel tState tAction tReaction
                     -> TFunction_View tState tReaction
                     -> TFunction_ModelAndViewCombined tState tAction
combineModelAndView change view = \(a, s) -> do
                   let (r, s') = change (a, s)
                   view (r, s')
                   return s'

--
type TFunction_ControllerLoop tState tAction =
  tState -> TFunction_ModelAndViewCombined tState tAction -> IO tState

I'm not saying that this is beautiful ;)

Erik Kaplun
  • 33,421
  • 12
  • 92
  • 102
Carsten
  • 49,407
  • 9
  • 85
  • 111
  • Yes, that could be an option. Thanks. (In C++ I would have defined template functions, depending on the types tAction, tState, tReaction). Thanks. – cibercitizen1 Oct 13 '15 at 14:20
0

I've managed to refactor the code to a simpler, readable and usable version using multi param typeclasses in this answer

Community
  • 1
  • 1
cibercitizen1
  • 19,104
  • 14
  • 65
  • 90