Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4111350
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 20, 20262026-05-20T22:03:18+00:00 2026-05-20T22:03:18+00:00

My specific problem is actually not about the general translation of an OO interface

  • 0

My specific problem is actually not about the general translation of an OO interface to Haskell. This is just the best title I could come up with. Yet, I’m sure that my problem originates from a still poor understanding of modeling code with Haskell and a mindset still located in the land of OO paradigms (still a haskell beginner, you see).

I’m writing a Mastermind (variation) simulation to test the fitness of several Mastermind strategies. As a matter of fact, I already did that in Java and Lua and thus this Haskell version is just an exercise for me to learn to program in Haskell. You can check out the readme of the Lua/Java version if you are interested in what I’m trying to achieve in the end.

But now for my concrete problem (in short and in OO terms): I want to provide an interface for strategies so that I can interchangeably put a strategy that adheres to that interface into the simulation recursion (loop) and after it’s done receive some data about the strategy’s performance. Additionally, I want to allow the strategy to keep arbitrary state around and I don’t want to care about what kind of state each strategy keeps around. But exactly this decision – which is actually essential – complicated everything. Another requirement, which concretely led to the problem describe below, is that a strategy name can be provided as a command line argument and then the simulation runs with that specific strategy.

At first I deemed a type class appropriate for these requirements but after not having come up with a real idea how to model the code this way I abandoned the idea. Then I decided for an ADT, used it ever since and came relatively far with the code – until now.


So, the superficial question is how to resolve the problem I provide below. The deeper question is how to better model my requirements for an interface with arbitrary state in Haskell.

Here is a reduced and adapted excerpt from my code:

-- reduced & simplified example
import Control.Monad.State

type Code = [Int]

data Answer = Answer { 
    blacks :: Int, 
    whites :: Int 
    } deriving (Eq, Show)

-- As you can see I decided for a type variable a that
-- represents the arbitrary state a strategy might carry
-- around. I wonder if this is the right way to do it.
-- | This is the interface for a strategy. A strategy must provide a method 
-- that, given a mastermind answer, returns the next guess, an initial state 
-- and the very first guess.
data Strategy a = Strategy {
    firstGuess :: Int -> Code,
    initialize :: Int -> a, -- a "constructor" in disguise
    guess      :: Answer -> State a Code
    }

dummy = Strategy {
    firstGuess   = firstGuess',
    initialize   = initialize', 
    guess        = guess'
    }

-- | The very first guess is always T0,T1,...,Tx, where x is the code length.
firstGuess' :: Int -> Code
firstGuess' length = [0..length-1]

-- | Memorize the code length
initialize' :: Int -> Int
initialize' = id

-- | Always return the same guess
guess' :: Answer -> State Int Code
guess' = const $ liftM firstGuess' get

-- HERE IS THE PROBLEM
-- I need this function since I'll get the name of a strategy
-- as a string from the command line and need to dispatch the
-- correct strategy to the simulation. Note, that there would
-- be of course more pattern matches for different strategies
-- with different accompanying states a.
nameToStrategy :: String -> Strategy a
nameToStrategy "dummy" = dummy

Executing the file yields the following error message:

Prelude> :l Problem.hs
[1 of 1] Compiling Main             ( Problem.hs, interpreted )

Problem.hs:37:25:
    Couldn't match expected type `a' against inferred type `Int'
      `a' is a rigid type variable bound by
          the type signature for `nameToStrategy' at Problem.hs:36:37
      Expected type: Strategy a
      Inferred type: Strategy Int
    In the expression: dummy
    In the definition of `nameToStrategy':
        nameToStrategy "dummy" = dummy
Failed, modules loaded: none.

I kind of can intuitively comprehend the problem. The problem seems to be that nameToStrategy cannot just return a Strategy with some state a. The type variable must be
concrete, since if I change the type of nameToStrategy to String -> Strategy Int everything’s fine. But that is not a solution to my problem.

I figured I need to relax the type. However, I don’t really know how to do it. I heard about Data.Dynamic and existential types and those might help me. Still, I feel that with a better modeling of my code I would not need those.


Edit: I managed to incorporate sclv’s suggestions into the code after all and it is much better now. The code for the strategies is clearer since I don’t need the special case for the first guess anymore and I can use guards to better distinguish between the case of a correct and an incorrect guess. The main simulation handling is not as elegant as sclv’s version since I put stepState (and the functions using stepState) into the IO Monad to measure computation time and thus have some “monadic syntax noise”. The ability to easily simulate a couple of simulation steps (which wasn’t actually possible before) helped me in finding a mutual recursive infinite loop (that bug was weird to understand). All in all, the code feels more discrete now. Needless to say, I don’t need the unsafeCoerce hack anymore to dispatch names to strategies (or better “packed strategies”). I hope the functional way of thinking someday will come naturally to me, too.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-20T22:03:18+00:00Added an answer on May 20, 2026 at 10:03 pm

    Ok let’s start from scratch. A pure strategy is a function that given a state of knowledge yields a guess. state -> Guess. For any given state, there’s some way to add new knowledge to it — Answer -> state -> state. Rather than an initial guess, we now just need an initial state.

    data Strategy state = Strategy {
                     initialState :: state,
                     extractGuess :: state -> Guess,
                     updateState  :: Answer -> state -> state
             }
    

    So now lets see what happns when we compose these functions.

    type Oracle = Guess -> Maybe Answer -- we'll encode success as Nothing
    
    stepState :: Oracle -> Strategy state -> state -> Maybe state
    stepState oracle str state = fmap (\ans -> updateState str ans state) $ 
                                          oracle (extractGuess str state)
    
    stepMany :: Strategy state -> Oracle -> [state]
    stepMany str oracle = go (initialState str)
          where go state = case stepState oracle str state of
                   Nothing -> []
                   Just newState -> newState : go newState
    

    So stepMany 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.

    type packedStrategy = Oracle -> Int
    
    packStrategy :: Strategy state -> PackedStrategy
    packStrategy str oracle = length $ stepMany str oracle
    

    And now you can write [packStrategy stratOne, packStrategy stratTwo] 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).

    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.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm also interested in more general thoughts, but here is my specific problem. In
This is a specific variation on the can't connect problem. In my case, I've
Unfortunately, the problem is not more specific than that. I've found a few examples
Yes, I have already asked this question, but the problem is much more specific.
I've created a custom exception for a very specific problem that can go wrong.
I have the problem that an specific step in Ant can only be executed
My problem is simple. I search a specific pattern in a file (let's say
I am having the problem that I cannot select a specific XML node which
This is a very specific question regarding MySQL as implemented in WordPress . I'm
This general topic has been asked here multiple times: how to render UITableViewCells with

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.