【问题标题】:Monad Transformer stack receives Non-type variable argument errorMonad Transformer 堆栈收到非类型变量参数错误
【发布时间】:2019-05-28 00:23:34
【问题描述】:

我已经开始使用monad-transformers: Step by step 的论文来了解 monad 转换器堆栈。 有些代码有点过时了,但经过一些细微的修改,我已经让它工作了。 但是现在我偶然发现了一条我不完全理解的错误消息。

error 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"

【问题讨论】:

  • 将错误消息复制并粘贴到您的问题中非常重要。 不要将其作为图像包含在内。文本图像对于视力受损的人来说是无法访问的,它们无法被搜索引擎索引,而且它们对每个人来说都是一种痛苦。

标签: haskell functional-programming monads monad-transformers


【解决方案1】:

您的代码中有一个错字,您在某些地方写了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 -&gt; Eval3 Value 更通用,因为它不符合标准,正如 chi 解释的那样。

【讨论】:

    【解决方案2】:

    默认情况下,GHC 使用基本的 Haskell 语言,正如 2010 年 Haskell 报告中所定义的那样。

    大多数现代 Haskell 代码不符合该标准,但会利用几个扩展。

    在这种情况下,您需要启用 FlexibleContexts 扩展,正如 GHC 在错误消息中所建议的那样。 在代码的最顶部添加这一行:

    {-# LANGUAGE FlexibleContexts #-}
    

    确实,在现代 Haskell 中启用多个扩展是非常习惯的。可以说,其中许多应该默认启用。

    【讨论】:

      猜你喜欢
      • 2011-01-06
      • 2014-05-03
      • 1970-01-01
      • 2015-11-01
      • 1970-01-01
      • 2016-02-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多