number_in_month练习(为什么x = x + 1被认为是sml中的bool,而x是int以及如何正确地表示x = x + 1?) [英] number_in_month exercise (Why x = x + 1 is considered bool in sml while x is int and how to say x = x + 1 correctly?)
问题描述
更新:我要用此代码执行的操作是获取日期,年/月/日和给定数字作为月份的列表,并检查给定列表中有多少个日期.与给定月份相同的月份.我所说的x = x + 1是x ++,例如在Java或C或C#中.作为输出,我要x.如果没有匹配,则为0,如果有任何匹配,则x = x + 1
Update: What I want to do with this code is to get a list of dates, year/month/day and a given number as a month, and check to see how many of the dates in the given list are in the same month as that given month. What I meant of x = x + 1 was x++ such as in java or C or C#. As the output I want x. if there is no match, 0 and for any match x = x + 1
这是我的代码,
fun number_in_month (Dlist : (int * int * int) list, Month : int, x : int) =
if null Dlist then x
else if #2 (hd Dlist) = Month then x = x + 1 andalso number_in_month (tl(Dlist), Month, x)
else number_in_month ((tl(Dlist)), Month, x)
它给了我错误:
Error: types of if branches do not agree [tycon mismatch]
then branch: int
else branch: bool
in expression:
if null Dlist
then x
else if (fn <rule>) (hd <exp>) = Month
then (x = <exp> + <exp>)
andalso (number_in_month (<exp>,<exp>,<exp>))
else number_in_month (tl <exp>,Month,x)
我真的不明白为什么sml考虑x = x + 1类型的bool.如果有人能告诉我如何正确地在sml中说x = x + 1,我将非常高兴.提前非常感谢.
I really don't get it why sml is considering x = x + 1 of type bool. I'd be really happy if someone could tell me how can I correctly say x = x + 1 in sml. Thanks a lot in advance.
推荐答案
在标准ML中说 x = x + 1
,您需要澄清您要说的内容,因为显然 x= x + 1
表示您不想要的东西.意思是将 x
与 x + 1
进行比较,并说它们是否相等"(它们永远不会是整数).
Saying x = x + 1
in Standard ML, you need to clarify what you intend to say, because clearly x = x + 1
means something you don't intend. What it means is "Compare x
with x + 1
and say if they are equal" (which they never will be of any integer).
我想您要实现的是将x更新为它的后继",如果不使用引用类型,这是不可能的,我不鼓励这样做,因为它们不是不可变的且不起作用.通常在功能上进行更新的方法是将更新的值传递给最终返回该值的函数.(由于将函数参数用作累积变量,因此感觉就像是在每次递归调用时更新其值的变量一样.)
What I suppose you want to achieve is "update x to its successor", which is not possible without the use of reference types, which I discourage since they are not immutable and functional. The way you usually update something functionally is by passing an updated value to a function that eventually returns it. (Using function arguments as accumulating variables, so it feels as if it's the same variables that update their value e.g. upon each recursive call.)
我建议您做的另一件事是使用模式匹配而不是if-then-else.例如,您知道列表与 []
匹配时为空.由于您的计算结果不是布尔值,因此您不能使用"... andalso ..."-我怀疑您这样做是因为您想同时做两件事,并且 andalso 闻起来像在做而且也在做其他事情",但这是一个误解.您可以这样做(例如,使用;
或 before
),但是您将失去结果,因为这些运算符处理了副作用,并丢弃了其中一个操作数的主要效果,因此这不是您想要的.
Another thing I recommend that you do is use pattern matching instead of if-then-else. For example, you know that the list is empty if it matches []
. Since the result of your computation is not a boolean, you cannot use "... andalso ..." -- I suspect you do this because you "want to do two things at once, and andalso smells like "doing something and also doing something else", but this would be a misconception. You can do this (using e.g. ;
or before
), but you would lose your result because these operators deal with side-effects and discard the main effect of one of their operands, so it is not what you want at this point.
这是我在暗中暗杀的目标,它是用模式匹配写的:
Here is my stab in the dark at what you intended, written using pattern matching:
fun number_in_month ([], _, x) = x
| number_in_month ((one,two,three)::dlist, month, x) =
if two = month then number_in_month(dlist, month, x+1)
else number_in_month(dlist, month, x)
已修改:您也可以在不进行尾递归的情况下执行此操作
Modified: You can also do this without tail-recursion
fun number_in_month([], _) = 0
| number_in_month((_,month1,_)::dlist, month2) =
if month1 = month2 then 1 + number_in_month(dlist, month2)
else number_in_month(dlist, month2)
或用不同的文字写
fun number_in_month([], _) = 0
| number_in_month((_,month1,_)::dlist, month2) =
(if month1 = month2 then 1 else 0) + number_in_month(dlist, month2)
或使用列表组合器:
fun counter(n1,n2) = if n1 = n2 then 1 else 0
fun number_in_month(dlist, month2) =
foldl (fn ((_,month1,_),count) => counter(month1,month2) + count) 0 dlist
或者按照您的要求使用参考,即使我不鼓励这样做:
Or using reference, as you asked for, even though I discourage this:
fun number_in_month (dlist, month2) =
let val count = ref 0
fun loop [] = !count (* the value inside the ref-cell *)
| loop ((_,month1,_)::dlist) =
if month1 = month2 then (count := !count + 1 ; loop dlist)
else loop dlist
in loop dlist end
如您所见,由于我希望在函数内创建引用单元,所以添加了一些复杂性,但是我无法在每次递归调用时都创建新的引用单元.因此,我创建了一个递归的帮助器函数,并让其具有在递归过程中更改的参数(它可以从 number_in_month的父作用域继承
month2
和 count
.当递归结束(基本情况)时,我选择返回ref-cell内的值(使用标准ML稍微模糊的语法进行解引用).
As you can see, some complexity is added because I wish to create the ref-cell within the function, but I cannot create a new ref-cell upon every recursive call. So I create a helper function that is recursive and let it have the argument that changes during recursion (it can just inherit month2
and count
from the parent scope of number_in_month
. When recursion ends (base case), I choose to return the value within the ref-cell (using Standard ML's slightly obscure syntax for dereferencing).
在掌握功能性方法之前,请不要养成使用ref单元的习惯.否则,您将不得不使用一种使这种习惯变得丑陋的语言进行强制性编码.:)
Don't make it a habit of using ref-cells before you master the functional way. Otherwise you are back to coding imperatively in a language that makes this habit ugly. :)
这篇关于number_in_month练习(为什么x = x + 1被认为是sml中的bool,而x是int以及如何正确地表示x = x + 1?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!