【问题标题】:Implementing functions in Haskell在 Haskell 中实现函数
【发布时间】:2021-12-04 07:28:26
【问题描述】:

我正在尝试使用我自己的类型别名和数据构造函数来实现一个 eval 函数。这个函数应该根据输入的 Func 返回一个更新的字典 Dict 和程序计数器 Counter。基本上,如果输入正确,我希望它增加计数器。 这些是我的类型别名:

type Counter = Int
type Name = String
type Dict = Map Name Const

这是我的数据构造函数:

data Func = GET_INT Int
          | GET_DICT Name
          | JUMP Counter
          deriving Show

这是具有函数的类,我在其中将 Func 设为它的实例:

class Evaluate a where
  eval ::  Func -> (Dict, Counter) -> Maybe (Dict, Counter)
 
instance Evaluate Func where
  eval (GET_INT a)(d, c) = Just(d, c+1)
  eval (GET_DICT a)(d, c) = Just(d, c+1)
  eval (JUMP a)(d, c) = Just(d, c+1)
  eval = Nothing

但是,我遇到了一些错误。首先,我得到以下信息:期望一个类型,但 'Counter' 有一种 'Const'

其次,我不确定我是否为 Evaluate 类输入了正确的参数,因为 a 没有在任何地方使用。另外,我认为函数的输入不会像上面那样工作。

任何人都可以帮助弄清楚如何使该功能起作用吗?

【问题讨论】:

  • 您包含的代码不会产生该错误。您的代码有很多很多问题;你写的东西没有什么意义,很难说你甚至想做什么。试着把这个问题分解成更小的部分,直到你得到足够小的东西,你可以清楚地询问它。
  • 你能指出我的第一个错误在哪里吗?
  • @m.18:例如你返回一个2元组,但是签名指定类型应该是Maybe (Dict, Counter),所以你需要返回一个包装了值的Just ...,或Nothing
  • 是的,我知道返回不正确,但我专注于输入类型,因为它给了我一个错误。你能在输入参数中发现我的错误吗?
  • 一个更新任何东西的函数例如是eval _ x = Just x

标签: function haskell types instance


【解决方案1】:

这些是我的类型:

type Counter = Int
type Name = String
type Dict = Map Name Int

这些是类型别名,但没关系。

这是我的数据类:

data Func = GET_INT Int
          | GET_DICT Name
          deriving Show

术语“数据类”没有任何意义。 Func 是一种类型。有两个数据构造函数。好的。

这是具有我正在尝试创建的功能的类:

class Evaluate a where
  eval ::  a -> (Dict, Counter) -> Maybe (Dict, Counter)

嗯,这没有多大意义。什么是eval,为什么要用a参数化?我认为首先定义eval :: Func -> (Dict, Counter) -> Maybe (Dict, Counter) 并认真思考为什么要使其更具多态性会更好。

eval (GET_INT a)([(d1, d2)],c) = ([(d1,d2)], c)
eval (GET_DICT a)([(d1, d2)],c) = ([(d1,d2)], c)

这是我得到的错误:“eval”的方程有不同数量的参数。

没有。使用您提供的代码,这不是错误。您应该始终提供用于产生导致您混淆的错误的实际代码。

实际错误一:

so.hs:15:20: error:
    • Couldn't match type ‘[(a0, b0)]’ with ‘Map Name Int’
      Expected type: Dict
        Actual type: [(a0, b0)]
    • In the pattern: [(d1, d2)]
      In the pattern: ([(d1, d2)], c)
      In an equation for ‘eval’:
          eval (GET_INT a) ([(d1, d2)], c) = ([(d1, d2)], c)
   |
15 |   eval (GET_INT a)([(d1, d2)],c) = ([(d1,d2)], c)

这是因为,除了少数例外,语法[ ... ] 是一个列表而不是一个映射。您不能在地图上进行模式匹配,而应该只匹配 env 等变量。

so.hs:15:36: error:
    • Couldn't match expected type ‘Maybe (Dict, Counter)’
                  with actual type ‘([(a0, b0)], Counter)’
    • In the expression: ([(d1, d2)], c)
      In an equation for ‘eval’:
          eval (GET_INT a) ([(d1, d2)], c) = ([(d1, d2)], c)
      In the instance declaration for ‘Evaluate Func’
    • Relevant bindings include
        d2 :: b0 (bound at so.hs:15:26)
        d1 :: a0 (bound at so.hs:15:22)
   |
15 |   eval (GET_INT a)([(d1, d2)],c) = ([(d1,d2)], c)

(a,b) 的元组与 Maybe (a,b) 不同。遗憾的是,您显然已经知道这一点,但粘贴了分散注意力的代码 - 在提出问题之前清理代码。

如果我们解决了这两个问题,那么我们会得到可以正常加载但完全没有价值的代码:

import Data.Map

type Counter = Int
type Name = String
type Dict = Map Name Int

data Func = GET_INT Int
          | GET_DICT Name
          deriving Show

class Evaluate a where
  eval ::  a -> (Dict, Counter) -> Maybe (Dict, Counter)
 
instance Evaluate Func where
  eval (GET_INT a) (env,c) = Just (env, c)
  eval (GET_DICT a) (env,c) = Just (env, c)

【讨论】:

  • 如果我要像这样实现 eval 函数: eval :: Func -> (Dict, Counter) -> Maybe (Dict, Counter) ,我如何包含类参数?因为这是我最初想要的,但很困惑。
  • 我已经更新了原始帖子中的代码,以使我的函数具有目的性。也就是说,根据 func 输入递增计数器。您能否检查一下它是否更有意义以及我在哪里弄错了?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多