2016-04-21 7 views
2

У меня есть этот фрагмент кодаоператор типа операнда несовпадение

fun decrement_to_zero r = if !r < 0 
          then r := 0 
          else while !r >= 0 do r := !r - 1 

из этого учебника

https://learnxinyminutes.com/docs/standard-ml/

Но я получаю эту ошибку:

stdIn:1.2-33.9 Error: operator and operand don't agree [literal] 
    operator domain: int ref 
    operand:   int 
    in expression: 
    decrement_to_zero 10 

, когда я называю его

- decrement_to_zero 10;

Почему?

ответ

3

Why?

Если вы проверяете тип подписи функция, в

- decrement_to_zero; 
> val it = fn : int ref -> unit 

Вы можете подтвердить, что его тип ввода не совпадает с 10 : int. Но если вы создаете int ref,

- val foo = ref 10; 
> val foo = ref 10 : int ref 

и передать в вашу функцию,

- decrement_to_zero foo; 
> val it =() : unit 

вы увидите, что ссылка была обновлена, но не до нуля,

- foo; 
> val it = ref ~1 : int ref 

Поэтому имя функции было довольно плохо выбрано и написано. Похоже, что с этим учебником многое пошло не так, как я изначально написал его.

Хотя стандарт ML имеет поддержку ссылок, часто более идиоматично писать чистые функции. Чистая функция принимает только значения в качестве входных данных и возвращает значения как выходные данные, но не влияет на мир вне функции (например, что указывает ссылка foo в любой данный момент времени). Так, например,

fun actually_decrement_to_zero n = 
    if n > 0 then actually_decrement_to_zero (n-1) else n 

И используя это,

- actually_decrement_to_zero 10; 
> val it = 0 : int 

Как вы можете видеть, результат приходит прямо из функции, а не косвенно, через ссылку.

+0

Несмотря на ошибку с этой функцией, она по-прежнему выглядит как хороший небольшой учебник. –

+0

Спасибо! Я изучил много программ из таких коротких учебников. Я оставил ссылки как преднамеренный выбор, потому что я думал, что он научит людей функциональному программированию правильным способом, но я понимаю теперь, что лучше научить плохой функции хорошим примером, чем плохим. ;-) –