I have this function:
addBinaryTreeNode((genRandomNumber(100), genRandomNumber(100), genRandomNumber(100)), tree, 1, [])
That returns a data type "binaryTree". It will compile when that is by itself, but when I have it in a function:
generate3DNodeTree(addBinaryTreeNode((genRandomNumber(100), genRandomNumber(100), genRandomNumber(100)), tree, 1, []), numToGen - 1)
...it will not compile, giving me these errors:
stdIn:215.21-215.135 Error: operator and operand don't agree [tycon mismatch]
operator domain: (int * int * int) * binaryTree * int * int list
operand: ((Random.rand -> int) * (Random.rand -> int) * (Random.rand -> int)) * binaryTree * [int ty] * 'Z list
in expression:addBinaryTreeNode((genRandomNumber 100,genRandomNumber 100,genRandomNumber 100),tree,1,nil)
The function "generate3DNodeTree" has arguments:
(tree : binaryTree, numToGen : int)
...which are exactly what I'm passing to it. Why doesn't this work?
generate3DNodeTree works if I pass it like so:
generate3DNodeTree(tree, numToGen - 1)
SMLNJ knows that the return type of addBinaryTreeNode is binaryTree, so I don't know what the issue could be.
The problem is that your genRandomNumber
doesn't return an int
. Instead it returns a function of type Random.rand -> int
, where Random.rand
is the type of a random number generator. You could change the definition of genRandomNumber
so that it evaluates this function at a generator and returns an int.
According to the documentation of the Random structure, the function Random.rand(i,j)
creates such a generator. In production code you would want to find a way to seed it from the system clock (which doesn't seem easy in SML) though for testing purposes you can just hard-wire in a specific i
and j
:
val generator = Random.rand(1,5)
fun genRandomNumber(numToGen) = Random.randRange(1, numToGen) generator;
Using these definitions, genRandomNumber
is now a function of type int -> int
, hence using this definition you won't have the same type mismatch error.