Using const in Halogen

In the basic Halogen example, in Button.purs I see

myButton :: forall m. H.Component HH.HTML Query Unit Message m
myButton =
  H.component
    { initialState: const initialState
    , render
    , eval
    , receiver: const Nothing
    }
  where

  initialState :: State
  initialState = false

Question: Why not just leave out const and have

{ initialState: initialState
, render
, eval
, receiver: Nothing
} 

After all, const takes two arguments so it seems that partial-application is at play here. But this seems unnecessarily complicated.

The initial state field is a function that takes input from a parent component, so you can set the initial state based on that and then subsequently handle the input in eval.

@pdavidow You could, in fact, do something similar to what you suggest:

myButton =
  H.component
    { initialState
    , render
    , eval
    , receiver: const Nothing
    }
  where

  initialState :: Input -> State
  initialState _ = false

Ultimately, as @paulyoung noted, you are expected to provide a function Input -> State to the component, named initialState. If you don’t care about the input, you’ll have to explicitly ignore it.

Most people, in that case, will just write a value for their initialState :: State and then use const to throw away the input. But you could also pattern match, as I’ve done here, or you could use const in the body of the function:

initialState: const initialState
initialState: \_ -> initialState
where
  initialState = false

same thing as

  { initialState
  , ... 
  }
  where
    initialState :: Input -> State
    initialState = const false
    initialState _ = false
    initialState = \_ -> false

But the most common use is:

  • If your initial state needs to be a function taking Input, then simply write that function and provide it in the record as { initialState: initialState }
  • If your initial state doesn’t require input at all, then write it as a simple value and use const to throw away the input argument as { initialState: const initialState }

I also like filling in the type signatures to make it clear what’s needed (this is approximate)

type MyComponentSpec =
  { initialState :: Input -> State
  , render :: State -> ComponentHTML
  , eval :: Query ~> ComponentDSL
  , receiver :: Input -> Maybe (Query Unit)
  }