Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Ok let's start from scratch. A pure strategy is a function that given a state of knowledge yields a guess. <code>state -&gt; Guess</code>. For any given state, there's some way to add new knowledge to it -- <code>Answer -&gt; state -&gt; state</code>. Rather than an initial guess, we now just need an initial state.</p> <pre><code>data Strategy state = Strategy { initialState :: state, extractGuess :: state -&gt; Guess, updateState :: Answer -&gt; state -&gt; state } </code></pre> <p>So now lets see what happns when we compose these functions.</p> <pre><code>type Oracle = Guess -&gt; Maybe Answer -- we'll encode success as Nothing stepState :: Oracle -&gt; Strategy state -&gt; state -&gt; Maybe state stepState oracle str state = fmap (\ans -&gt; updateState str ans state) $ oracle (extractGuess str state) stepMany :: Strategy state -&gt; Oracle -&gt; [state] stepMany str oracle = go (initialState str) where go state = case stepState oracle str state of Nothing -&gt; [] Just newState -&gt; newState : go newState </code></pre> <p>So <code>stepMany</code> is 90% of what we want, but its still polymorphic in that pesky state param. That's easy enough to work around -- after all we want the number of steps, not the intermediate states of the steps themselves.</p> <pre><code>type packedStrategy = Oracle -&gt; Int packStrategy :: Strategy state -&gt; PackedStrategy packStrategy str oracle = length $ stepMany str oracle </code></pre> <p>And now you can write <code>[packStrategy stratOne, packStrategy stratTwo]</code> etc. And along the way, we've discovered something important -- what you care about from your strategy is just that it is a function from some problem (represented by an oracle) to the steps it takes to solve the problem. And one way (not the only way) to produce such stratgies is to provide a way to ask for new knowledge (to guess) and a way to update our knowledge (update state). </p> <p>This is not the only answer, and maybe not ideal for your purposes, but it should help to move you towards thinking with functions and types rather than objects and capabilities.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. COYour answer is good since it made me think really hard about how I could apply this design/thinking to my application. However, there are some problems (specific to my requirements) that make this difficult. E.g., I'm not only interested in the number of steps but also additional information (like distance traveled, real time taken for computation - its a "planar" variation of mastermind). So, I could not (yet) come up with a redesign but at least now I have a reference to turn to when I feel experienced enough to take a stab at it. So, thanks for your answer!
      singulars
    2. CONonetheless I have two questions: 1. You use the state of the strategy as an explicit argument. I guess, you could have also used the State Monad. Is the reason to not use the State Monad to keep things simple for your explanation or is there another one? 2. If I understand correctly I could now write `nameToStrategy` like so: `nameToStrategy "dummy" = packStratgey dummy :: String -> PackedStrategy` and to evaluate the code I need to provide an Oracle (or in my case the simulation function), so like `let str = nameToStrategy "dummy" in str oracle`? And this works as `nameTo..` has no type var?
      singulars
    3. CO@WugenFirst. Rather than a list of states, (which we then take the length of), you can produce a monomorphic list of anything -- distance travelled, time taken, guess, etc. The principle is the same. Second -- yep the state monad works too, I just didn't see a need for it. Last -- nameToStrategy is just looking up the strategy (which has no type var) in a map or list of some sort.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload