Стек Monad Transformer получает ошибку аргумента переменной типа - PullRequest
0 голосов
/ 31 декабря 2018

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

ошибка msg

Насколько я понимаю, m :: * -> *имеет более высокий вид, и компилятор хочет, чтобы это была переменная, т. е. m :: *.Но я не знаю, как мне нужно редактировать свой код, чтобы это работало.

import Control.Monad.Identity
import Control.Monad.Error
import Control.Monad.Reader
import Control.Monad.State
import Control.Monad.Writer
import Control.Monad.Fail
import Data.Maybe
import qualified Data.Map as Map

type Name = String -- variable names
data Exp = Lit Integer -- expressions
         | Var Name
         | Plus Exp Exp
         | Abs Name Exp
         | App Exp Exp
         deriving (Show )

data Value = IntVal Integer -- values
           | FunVal Env Name Exp
           deriving (Show )
type Env = Map.Map Name Value -- mapping from names to values

type Eval3 α = ReaderT Env (ErrorT String Identity) α

runEval3 :: Env -> Eval3 α -> Either String α
runEval3 env ev = runIdentity (runErrorT (runReaderT ev env ))


evel3 :: Exp -> Eval3 Value
evel3 (Lit i)= return $ IntVal i
eval3 (Var n) = do env <- ask
                   case Map.lookup n env of
                     Nothing -> throwError ("unbound variable: " ++ n)
                     Just val -> return val
eval3 (Plus e1 e2 ) = do e1' <- eval3 e1
                         e2' <- eval3 e2
                         case (e1' , e2') of
                            (IntVal i1 , IntVal i2 ) -> return $ IntVal (i1 + i2 )
                            _ ->throwError "type error in addition"
eval3 (Abs n e) = do env <- ask
                     return $ FunVal env n e
eval3 (App e1 e2 ) = do val1 <- eval3 e1
                        val2 <- eval3 e2
                        case val1 of
                          FunVal env' n body -> local (const (Map.insert n val2 env')) (eval3 body)
                          _ -> throwError "type error in application"

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

В вашем коде есть опечатка, в некоторых местах вы написали evel3 вместо eval3:

evel3 :: Exp -> Eval3 Value
evel3 ... = ...
eval3 ... = ...

Это заставляет GHC полагать, что это два разных определения

-- One definition
evel3 :: Exp -> Eval3 Value
evel3 ...  = ...

-- Another definition, without a signature
eval3 ... = ...

GHC отклоняет предполагаемый тип для eval3, который является гораздо более общим, чем Exp -> Eval3 Value, потому что он не соответствует стандарту, как объяснил Чи.

0 голосов
/ 31 декабря 2018

По умолчанию GHC использует базовый язык Haskell, как он определен в отчете Haskell 2010 года.

Большинство современных кодов на Haskell не соответствуют этому стандарту, но используют несколько расширений.

В этом случае вам нужно включить расширение FlexibleContexts, как GHC предлагает в сообщении об ошибке.Добавьте эту строку в самый верх вашего кода:

{-# LANGUAGE FlexibleContexts #-}

Действительно, в современном Haskell очень удобно включать несколько расширений.Возможно, многие из них должны быть включены по умолчанию.

...