Вставить строку, начиная с указанного индекса - PullRequest
0 голосов
/ 01 мая 2018

Я совершенно новичок в Хаскеле. Мне нужно вставить данную строку по заданному индексу строки, которая может быть уже непустой.

Это то, что я имею до сих пор. Тем не менее, после запуска без ошибок, когда я спрашиваю, что значение t является ghci, просто зависает бесконечно.

Haskell:

create = ("",0,0,"","")

addText (m,l,p,_,k) i = 
    let a = take p m
        m = drop p m
        full = a++i++m
    in (full, length full, p + length i, "", k)

Где m - текст для добавления, l - длина m, а p - индекс для начала добавления новой строки в

Выход:

*Main> t = create

*Main> t

("",0,0,"","")

*Main> t = addText t "test"

*Main> t

(hangs)

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Как и многие новички в Haskell, вы пишете функции в стиле императив , где вы обновляете переменные.

Переменная в Haskell, однако, не может быть обновлена: (пере) не присваиваете значение переменной, вы объявляете переменную. Если вы пишете i = i + 1, вы не берете старое значение i и добавляете к нему 1, здесь вы объявляете i в терминах самого себя, поэтому i = i + 1, означает, что мы написали бесконечное глубокое рекурсивное выражение i = ( ( (...) + 1) + 1) + 1.

В вашей функции вы, кажется, обновляете m:

addText (<b>m</b>, l, p, _, k) i = 
    let a = take p <b>m</b>
        <b>m</b> = drop p <b>m</b>
        full = a++i++<b>m</b>
    in (full, length full, p + length i, "", k)

Итак, вы написали m в терминах самого себя, и хотя из-за лени это не будет per se loop, в случае необходимости значения m, мы застрянем в бесконечности рекурсии.

Используя новую переменную, мы можем решить проблему:

addText (<b>m</b>, l, p, _, k) i = 
    let a = take p <b>m</b>
        <b>z</b> = drop p <b>m</b>
        full = a++i++<b>z</b>
    in (full, length full, p + length i, "", k)

То же явление происходит, если вы напишите:

Prelude> t = addText t "test"

вы снова определяете t в терминах самого себя. Таким образом, вам лучше использовать другую переменную или константы:

Prelude> t = addText ("",0,0,"","") "test"
0 голосов
/ 01 мая 2018
let m = drop p m

- это круговое определение. Это не означает «установить m меньше, чем m раньше», потому что помните, что невозможно изменить переменные в Haskell. Вместо этого вы игнорируете существующую m и определяете новую переменную с именем m, определяемую самим собой: оценка, которая никогда не может быть завершена. Это может показаться глупой особенностью, но в других ситуациях на самом деле весьма полезно определять значения в терминах самих себя, поэтому язык это позволяет.

Затем вы снова совершаете ту же ошибку, набрав

t = addText t "test"

определяет t в терминах самого себя.

Вы можете исправить обе эти ошибки, используя переменные с уникальными именами, например,

r = addText t "test"

В этот момент вы столкнетесь с новыми замечательными ошибками: подпись выведенного типа create не совпадает с подписью выведенного типа для addText из-за правил по умолчанию. Если вы укажете явные подписи типов или вставите определение create, вы, наконец, получите то, что хотели:

*Main> addText ("",0,0,"","") "test"
("test",4,4,"","")
...