2
votes

I am trying to write my first function in sml. It takes a tuple and returns the sum of first element times 10, second element times 6 and the third, and then divides by 10. I don't know what I am doing wrong here I get this error operator and operand do not agree [tycon mismatch].

fun rgb2gray(rgb: (int*int*int))=
let
    val x = (#1rgb * 3 )+ (#2rgb * 6 )+ (#3rgb)
in  
    x=x/10
end
3

3 Answers

3
votes

x=x/10 is an equality comparison (and will only be true if x is zero), and / is for dividing reals, not integers.
(+, -, and * are overloaded, but / isn't.)

Integer division is called div, and since the value of the function should be x div 10, you only need to write x div 10, without any =.

It's more common to use pattern matching than selectors for deconstructing structures, and I would write your function like this:

fun rgb2gray (r, g, b) = (r * 3 + g * 6 + b) div 10
2
votes

Since molbdnilo already provided an answer, here is an alternative way you can do this using records:

type rgb = { r : int, g : int, b : int }

fun rgb2gray (color : rgb) : int =
    (#r color * 3 +
     #g color * 6 +
     #b color) div 10

or equivalently by pattern matching on records:

fun rgb2gray ({ r = r, g = g, b = b } : rgb) : int =
    (r * 3 + g * 6 + b) div 10

Records are like tuples, but where their parts are named rather than numbered (hence #r instead of #1). The syntax is a bit more fiddly, but the upside is that you don't accidentally mix two colors up as easily. Perhaps for RGB values it's hard to mix them up anyway, since the notion of R, G and B in that exact order is quite ingrained into a lot of programmers. Still, this is another option.

1
votes

Since it appears that others have already helped you solve the problem I thought that I would point out that after the end you need an ; after it since the function is done.