Латинская функция в SML (ошибка оператора и операнда) - PullRequest
0 голосов
/ 16 ноября 2018

Я практикую sml, используя проблемы из второго издания Ullman (M97). Проблема, над которой я сейчас работаю, вызывает функцию piglatin, которая берет слово, разбивает его и проверяет, является ли первый символ гласным (a, e, i, o u). Если это гласный, он вставляет список символов обратно в строку и добавляет «yay» в конце. Если первый символ не является гласным, функция проверяет остальные символы, пока не встретит первый гласный. Когда это происходит, он помещает все символы, которые были перед первым гласным, в конец списка символов, возвращает новый список символов обратно в строку и добавляет к нему «ay».

Например:

- pl "able";
val it = "ableyay" : string

- pl "stripe";
val it = "ipestray" : string

fun isVowel (c::cs) = 
    if c = #"a" then true
    else if c = #"e" then true
    else if c = #"i" then true
    else if c = #"o" then true
    else if c = #"u" then true
    else false

fun cycle nil = nil
  | cycle (h :: hs) = hs @ [h]

fun aL (h::hs) =
    if isVowel(h) = true
    then h :: hs
    else aL (cycle (h :: hs))

fun plx (x) =
    if isVowel x = true
    then (implode x) ^ "yay"
    else implode (aL (x)) ^ "ay"

fun pl (x) =  plx (explode x)

У меня большая часть проблемы решена, но я застрял на том, почему моя функция plx дает мне это:

Error: operator and operand don't agree [tycon mismatch]  
operator domain: char list list  
operand:         char list 
in expression: aL x uncaught exception Error

и я не уверен, как это исправить.

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Вы можете найти SML-трек Exercism приятным тогда. Есть даже Pig Latin упражнение. : -)

Довольно часто взрывать, анализировать и взрывать, но это не очень эффективно, а в некоторых случаях и не легче. Как указало molbdnilo, isVowel, вероятно, должно принять char в качестве ввода вместо char list:

fun isVowel c =
    c = #"a" orelse
    c = #"e" orelse
    c = #"i" orelse
    c = #"o" orelse
    c = #"u"

Для функции, которая преобразует слово в латинский, вы можете сделать это полностью с помощью строковых функций:

fun piglatin (word : string) =
    let val firstLetter = String.sub (word, 0)
    in if isVowel firstLetter
       then word ^ "yay"
       else String.extract (word, 1, NONE) ^ str firstLetter ^ "ay"
    end

Проверка этого:

- piglatin "pig";
> val it = "igpay" : string

- piglatin "ant";
> val it = "antyay" : string

Теперь есть угловые шкафы:

  • Что если слово пустое ""?

    - piglatin "";
    ! Uncaught exception:
    ! Subscript
    
  • Что если слово в верхнем регистре "Ant"?

    - piglatin "Ant";
    > val it = "ntAay" : string
    

Эти две проблемы необходимо решить, чтобы сделать функцию piglatin на основе строк надежной и всего .


Вот несколько отзывов о решении, которое вы разместили:

  • Не пишите if P then true else Q; написать P orelse Q.
  • Не пишите isVowel c = true; написать isVowel c.
  • aL и plx не лучшие имена функций; Я не уверен точно, что они должны делать, кроме как действовать как клей между pl и cycle, isVowel, explode и implode.
0 голосов
/ 16 ноября 2018

Это потому, что тип isVowel равен char list -> bool.

Если вы посмотрите на aL:

fun aL (h::hs) = if isVowel(h) = true then h :: hs
                 else aL (cycle (h :: hs));

, то isVowel(h) означает, что h должно бытьchar list, а это, в свою очередь, означает, что aL должен иметь тип char list list -> char list list, а implode (aL x) - ошибка.

Чтобы исправить, измените isVowel на char -> bool:

fun isVowel c = ...

и напишите isVowel (hd x) в plx.

...