You need parens here:

| FullGame(t) -> List.reduce TotalRingCount (GameTower(t))

or if you prefer, just

| FullGame(t) -> List.reduce TotalRingCount (GameTower t)

(It still won't typecheck, but that will get you past this error.)

By on 11/14/2009 2:24 AM ()

You need parens here:

| FullGame(t) -> List.reduce TotalRingCount (GameTower(t))

Well, I then get this error: Expecting a int -> int -> int but given a int -> Game -> int. The type 'int' does not match the type 'Game

I suppose that List.reduce which expects ('T -> 'T -> 'T) means that all types 'T must be the very same type? Which would mean that what I'm trying to do here (pass my TotalRingCount to List.reduce) is impossible?

By on 11/14/2009 8:48 AM ()

Right; List.reduce requires them to be the same type. Perhaps you want List.fold instead?

[link:msdn.microsoft.com]

I was unclear what your overall goal was.

By on 11/14/2009 12:24 PM ()

Perhaps you want List.fold instead?

Well, I just want a function that takes the towers and sums the ints therein. Here is the current snippet:

//////////
type Tower = ( string * list<int> )
type Towers = list<Tower>

type Game =
| GameTower of Tower
| FullGame of Towers

let rec TotalRingCount (state:Game) (accum:int) =
match state with
| GameTower(t) -> accum // sum int list here
| FullGame(t) -> List.fold TotalRingCount t:>Towers 0
//////////////

Now the error at the last 0 is Unexpected integer literal in expression. Expected incomplete structured construct at or before this point or other token.

Expected incomplete structured construct? And if I take away the casting of t:>Towers I get a completely different error. I'm confused; this seems like it should compile.

By on 11/14/2009 7:15 PM ()

To get the code to parse, you need to add parens again, this time around (t:>Towers). More generally, when calling

f x y z

if any of x/y/z are expressions more than just a single token, then you need to parenthesize them (the way I stated it is only an approximate rule, but hopefully this will steer you some).

This is still nowhere near compiling, but it's getting closer; I rearranged the order of argument to match those of List.fold:

1
2
3
4
let rec TotalRingCount (accum:int) (state:Game) =
  match state with  
  | GameTower(t) -> accum  // sum int list here
  | FullGame(t) -> List.fold TotalRingCount 0 (t:>Towers)

That is, since it seems you want the whole function to return an int, that means the 'State type parameter of List.fold should be an int:

[link:msdn.microsoft.com]

But right now the 'T parameter is a Game, so the last argument to List.fold should be a "Game list", but there's no object of that type to be found. These data structures seem unusual; it seems like changing the types may be better for whatever you're trying to model.

By on 11/14/2009 10:34 PM ()

... right now the 'T parameter is a Game, so the last argument to List.fold should be a "Game list", but there's no object of that type to be found. These data structures seem unusual; it seems like changing the types may be better for whatever you're trying to model.

The data structures may be unusual, but I still wish I could understand compilation.

  • TotalRingCount takes arg of type Game
  • I'm passing t which is of option type FullGame which maps to type Towers which is of type list<Tower>
  • This would seem to mean that each call from list t to TotalRingCount would pass a Tower object. The discriminated union type Game contains option GameTower which maps to type Tower.
  • Thus, a Tower object seems like it should be compatible with a Game type. What am I missing?
By on 11/14/2009 11:24 PM ()

It's not because you have type Game = FullGame of Towers | GameTower of Tower that you can pass Tower to a function that expects a Game. If you want to pass a Tower to a function expecting a Game, then you need to use the GameTower constructor as in the following.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
type Tower = ( string * list<int> )


type Towers = list<Tower>

type Game =


  | GameTower of Tower


  | FullGame of Towers

let rec TotalRingCount = function


  | GameTower tower -> 0


  | FullGame towers -> 


      towers |> List.fold (fun accum tower ->  


        accum + TotalRingCount (GameTower tower)


      ) 0

By on 11/15/2009 5:12 AM ()

Thanks so much. The main thing I was missing was that I could not use the main TotalRingCount as the function to pass to fold; rather I needed (as you demonstrated) to pass a separate function that would have the accumulator.

By on 11/15/2009 11:04 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper