печать строки и вызов рекурсивной функции

В настоящее время я изучаю sml, но у меня есть один вопрос, на который я не могу найти ответ. Я погуглил, но все еще ничего не нашел.

Это мой код:

fun diamond(n) =
  if(n=1) then (
    print("*")
  ) else (

    print("*")
    diamond(n-1)

  )

diamond(5);

Это не работает. Я хочу, чтобы в коде отображалось столько *, сколько есть число n, и я хочу сделать это с помощью рекурсии, но я не понимаю, как это сделать.

Я получаю сообщение об ошибке при попытке запустить этот код. Это ошибка:

Standard ML of New Jersey v110.78 [построено: 20 августа, 19:23:18 2015] [открытие a4_p2.sml] a4_p2.sml: 8.5-9.17 Ошибка: оператор не является функцией [tycon mismatch] оператор: единица измерения в выражении : (print "*") diamond / usr / local / bin / sml: Неустранимая ошибка - Неперехваченное исключение Ошибка с 0 возникает в ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27

Спасибо


person zeeks    schedule 10.10.2015    source источник
comment
Какой у вас результат?   -  person Academiphile    schedule 10.10.2015
comment
@Zabari Я получаю сообщение об ошибке. Это ошибка: Standard ML of New Jersey v110.78 [построено: 20 августа, 19:23:18 2015] [открытие a4_p2.sml] a4_p2.sml: 8.5-9.17 Ошибка: оператор не является функцией [несоответствие tycon] оператор: единица измерения в выражении: (print *) diamond / usr / local / bin / sml: Fatal error - Uncaught exception Ошибка с 0, возникшим в ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27   -  person zeeks    schedule 10.10.2015


Ответы (1)


Вы можете вызвать побочные эффекты в ML, используя ';' Он будет оценивать все, что стоит перед ';' и отбросьте его результат.

   fun diamond(n) =
      if(n=1)
      then (print "*"; 1)
      else (print "*"; diamond(n-1));

    diamond(5);

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

Если бы вам было разрешено делать следующее:

      if(n=1)
      then 1
      else print "*";

тогда компилятор получит другую типизацию для веток then и else соответственно. Для ветви then типом будет int -> int, тогда как типом ветви else будет int -> unit. Такая дихотомия не допускается в строго типизированном языке.

Поскольку вам нужно оценить единичный тип, вы поймете, что ML не поддерживает выполнение блока инструкций, как мы обычно видим в других парадигмах, которые наивно перенесены в ML, будут отображать что-то вроде этого:

....
    if(n=1)
    then (print "1"
          print "2"
         )
    else (print "3"
          diamond(n-1)
         )
...

потому что какой тип будет оценивать ветвь then? int -> unit? Тогда как насчет другого оператора печати? Оператор должен возвращать единичный результат (даже составной), чтобы это не имело смысла. А что насчет int -> unit * unit? Нет проблем с этим, за исключением того, что синтаксически вы не смогли передать кортеж компилятору.

По этой причине БУДЕТ работать следующее:

fun diamond(n) =
  if(n=1)
  then (print "a", 1)  /* A tuple of the type unit * int */
  else diamond(n-1);

diamond(5);

В этом случае у вас есть функция типа int -> unit * int.

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

Что касается вашей фактической цели, следующий способ лучше написать функцию, алмаз как тип int -> string:

fun diamond(n) =
  if(n=1)
  then "*"
  else "*" ^ diamond(n-1);

print( diamond(5) );

Вышеупомянутый способ больше подходит для целей отладки.

person Kevin Johnson    schedule 10.10.2015
comment
Спасибо, это работает, но я не понимаю, почему 1 после print *; - person zeeks; 10.10.2015
comment
Это совсем не нужно. Я просто включил это, чтобы подчеркнуть иллюстрацию побочных эффектов. Это тоже отлично работает: fun diamond(n) = if(n=1) then print "*" else (print "*"; diamond(n-1)); diamond(5); - person Kevin Johnson; 10.10.2015