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 891459
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T13:53:40+00:00 2026-05-15T13:53:40+00:00

This question is more a semantic-algorithmic-data-structure question than a F# syntactically question. I have

  • 0

This question is more a semantic-algorithmic-data-structure question than a F# syntactically question.
I have a Minimax algorithm. The minimax algorithm should return the best next move, from a start position. To do this, it calculus all next moves, then the next-next-moves until a determined depth or until there is no more moves. It builds a tree like this:

     P  
   /  \  
 a      b  
/ \  
c d

I have the fallowing data struct to handle the tree:

type TreeOfPosition =
    | LeafP   of Position * int
    | BranchP of Position * TreeOfPosition list

In the exemple tree above, P and a are Branchs and b, c and d are Leafs. The code below is my minimax algorithm:

let evaluateTree ( tree : TreeOfPosition, player : int) =
    let rec loop minOrmax node =
        match node with
        | LeafP(position, 0) -> 
            LeafP(position, evaluateLeaf(position))
        | BranchP(position, children)  -> 
            minimax.[minOrmax](List.map (loop (1 - minOrmax)) children)
    loop player tree

This code are returning me a Leaf, for example, c. When I changed the recursion call to

| BranchP(position, children)  -> 
    LeafP(position, 
          getStaticEvalFromNode(minimax.[minOrmax](
                       List.map (loop (1 - minOrmax)) children)))

And this modification makes the static value of a good leaf go up.
I need to return the best second level node.
Hope somebody can help!
Pedro Dusso

EDIT 1

Thanks for all answers guys, they help me a lot. Sorry about didn’t specified the things very much. Let’s go in parts:

1) I’m matching my LeafP like LeafP(position, 0) because when I create my tree I set the leafs with a default value of 0 as its static value. As I’m going up my static values, eliminating the leaf and making the (before Branches) leafs with (min or max) static values I thought that this way I would prevent to evaluate a ex-Branch leaf (because it would not have the 0 value).

2) My biggest problem was to get the second level (the next move which has to be played) best position back. I solved it this way:

let evaluateTreeHOF ( tree, player : int) =
    let rec loop minOrmax node =
        match node with
        | LeafP(position, 0) -> LeafP(position, evaluateLeaf(position))
        | BranchP(position, children) -> LeafP(position,(children 
                                                         |> List.map (loop (1 - minOrmax)) 
                                                         |> minimax.[minOrmax] 
                                                         |> getStaticEvalFromNode))
    match tree with
    | BranchP(position, children) -> children |> List.map (loop (1 - player)) |> minimax.[player]

Instead of passing the entire tree, I’m passing just the children’s of the start node, and filtering the resulted list (a list of ex-Branches with the static values which went up for be the best for its current level) again. This way I’m getting the node I wanted.

I thought the kvb answers very interesting, but a little complicated to me. The other ones I understudied, but they just give me back the static value – and I could not make them to work for me 🙁

Thanks a lot for all the answers, all of them inspired me a lot.

Here is my full code: (http://www.inf.ufrgs.br/~pmdusso/works/Functional_Implementation_Minimax_FSharp.htm)

Pedro Dusso

  • 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-15T13:53:41+00:00Added an answer on May 15, 2026 at 1:53 pm

    I don’t quite understand some aspects of your sample (e.g. why do you match only against leaves with 0s in them?), so I’ll make a few changes below. First of all, let’s generalize the tree type a bit, so that it can store any types of data in the leaves and branches:

    type Tree<'a,'b> = 
    | Leaf of 'a 
    | Branch of 'b * Tree<'a,'b> list
    

    Let’s also use a dedicated player type, rather than using 0 or 1:

    type Player = Black | White
    

    Finally, let’s generalize the evaluation of the best move a bit, so that the leaf evaluation function is passed in as an argument:

    let bestMove evalPos player tree =
      // these replace your minimax function array
      let agg1,agg2,aggBy = 
        match player with
        | Black -> List.min, List.max, List.maxBy
        | White -> List.max, List.min, List.minBy
    
      // given a tree, this evaluates the score for that tree
      let rec score agg1 agg2 = function
      | Leaf(p) -> evalPos p
      | Branch(_,l) -> agg1 (List.map (score agg2 agg1) l)
    
      // now we use just need to pick the branch with the highest score
      // (or lowest, depending on the player)
      match tree with
      | Leaf(_) -> failwith "Cannot make any moves from a Leaf!"
      | Branch(_,l) -> aggBy (score agg1 agg2) l 
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I suppose this question is more general than working with COM components. I have
ASP.Net MVC3 is cool and all but I have this question more out of
This question is more philosophical than technical. I've trained myself as a web developer
This question is more UI/Design-ish than hard-core programming is. Background: I've been coding in
This question is more about guidance than actually solving my problem: I need to
This question is more a re-insurance than one directly about how to code. As
This is a code review question more then anything. I have the following problem:
The question I have might be more to do with semantics than with the
This is more of a conceptual question than an actual implementation and am hoping
I have been reading through this similar question and find myself less than satisfied

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.