Проблема с определенным для цикла в Haskell - PullRequest
3 голосов
/ 17 декабря 2010

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

Создание интерпретатора с помощью typedef:

interp :: Env -> Expr -> M Val

, который обрабатывает циклы в этом формате:

for ( var = expr to expr ) ( expr )

Конструктор данных определен следующим образом:

data Val =
   ValInt Int
 | ValBool Bool
 | ValFun (Val -> M Val)
 | ValRecFun (Val -> Val -> M Val)
 | ValRef Loc
 | ValNil

И расширенная среда определена как:

extendEnv :: Identifier -> Val -> Env -> Env
extendEnv var val (Env bs) = Env ((var,val):bs)

Вот где я нахожусь:

interp env (For x e1 e2 e3)       = do
                                      (ValInt v1) <- interp env e1
                                      (ValInt v2) <- interp env e2
                                      if (v1 < v2)
                                        then 
                                            let nenv = extendEnv x e1 env in do
                                                interp nenv e3
                                                interp env (For x e1 e2 e3)
                                        else return ValNil

Очевидно, я не хочу передавать "e1" в рекурсивный вызов цикла for, а скорее увеличивать вычисляемую переменную "v1" ..... но я не могу понять, как передать правильное выражение "v1".Достаточно ли этого направления, чтобы получить небольшую помощь? :)

* ОБНОВЛЕНИЕ *

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

interp env (For x e1 e2 e3)= do
                          (ValInt v1) <- interp env e1
                          (ValInt v2) <- interp env e2
                     return doLoop x v1 v2 env e3

doLoop :: Identifier -> Int -> Int -> Env-> Expr -> M Val
doLoop x v1 v2 env e3 = 
                 if v1 > v2 then return ValNil
                 else
                    let nenv = extendEnv x (ValInt v1) env in
                    interp nenv e3
                    doLoop x (ValInt (v1+1)) v2 nenv e3

ОБНОВЛЕНИЕ

Кажется, у меня возникла проблема с моим определением, а именно:

return doLoop x v1 v2 env e3 

Не может соответствоватьожидаемый тип M Val' against my inferred type Expr -> M Val '.

Я делаю здесь какую-то глупую ошибку?

Ответы [ 2 ]

0 голосов
/ 18 декабря 2010

Очевидно, что я не хочу передавать "e1" в рекурсивный вызов цикла for, а скорее увеличить вычисленную переменную "v1" .... но я не могу понять, как передатьэто правильное выражение "v1".Достаточно ли этого направления, чтобы получить небольшую помощь? :)

У вас уже есть «чистое» представление переменной e1 в v1, вы можете просто добавить 1 к v1 и упакуйте его.Замените makeConstExpr на то, что вы используете для создания Expr.

interp env (For var start end body) = do 
 (ValInt s) <- interp env start
 (ValInt e) <- interp env end 
 if s <= e 
   then
       let envn = extendEnv var (ValInt s) env in do
     interp envn body
     interp env (For var (makeConstExpr (s + 1)) end body) 
   else return ValNil

(мне кажется, что я недавно набирал это ...)

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

Редактировать: В зависимости от того, как выделая вашу мутацию, вы можете передать nevn вместо env в interp env (For var (ValInt (s + 1)) end body).

0 голосов
/ 18 декабря 2010

Я думаю, ты почти у цели. Взгляните на это (работая с Ints напрямую, упаковывая их в Vals, когда это необходимо, исправили небольшую проблему с ограничением количества паренов, и передавая только env в рекурсивном вызове):

doLoop :: Identifier -> Int -> Int -> Env -> Expr -> M Val
doLoop x v1 v2 env e3 = 
                 if v1 > v2 then return ValNil
                 else
                    let nenv = extendEnv x (ValInt v1) env in 
                    interp nenv e3
                    doLoop x (ValInt (v1+1)) v2 env e3
...