Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function Haskell中的抽象函数_Function_Haskell_Types_Parameters - Fatal编程技术网

Function Haskell中的抽象函数

Function Haskell中的抽象函数,function,haskell,types,parameters,Function,Haskell,Types,Parameters,我目前正在Haskell学习一门课程,在理解函数如何作为参数传递时遇到了一些困难。在这项任务中,我们的任务是创建一个计算表达式的程序。为了减少计算量,我想通过创建一个助手函数来抽象该函数,该函数将接受一个操作符作为输入并返回结果 主要功能: eval :: EDict -> Expr -> Maybe Double eval _ (Val x) = Just x eval d (Var i) = find d i eval d (Add x y) = evalOp d (+) x y

我目前正在Haskell学习一门课程,在理解函数如何作为参数传递时遇到了一些困难。在这项任务中,我们的任务是创建一个计算表达式的程序。为了减少计算量,我想通过创建一个助手函数来抽象该函数,该函数将接受一个操作符作为输入并返回结果

主要功能:

eval :: EDict -> Expr -> Maybe Double
eval _ (Val x) = Just x
eval d (Var i) = find d i
eval d (Add x y) = evalOp d (+) x y
eval d (Mul x y) = evalOp d (*) x y
eval d (Sub x y) = evalOp d (-) x y
evalOp:: EDict -> ((Num a) => a -> a -> a) -> Expr -> Expr -> Maybe Double
evalOp d op x y =
  let r = eval d x
      s = eval d y
  in case (r, s) of
    (Just m, Just n) -> Just (m `op` n)
    _                -> Nothing
辅助功能:

eval :: EDict -> Expr -> Maybe Double
eval _ (Val x) = Just x
eval d (Var i) = find d i
eval d (Add x y) = evalOp d (+) x y
eval d (Mul x y) = evalOp d (*) x y
eval d (Sub x y) = evalOp d (-) x y
evalOp:: EDict -> ((Num a) => a -> a -> a) -> Expr -> Expr -> Maybe Double
evalOp d op x y =
  let r = eval d x
      s = eval d y
  in case (r, s) of
    (Just m, Just n) -> Just (m `op` n)
    _                -> Nothing
其他定义

data Expr
  = Val Double
  | Add Expr Expr
  | Mul Expr Expr
  | Sub Expr Expr
  | Dvd Expr Expr
  | Var Id
  | Def Id Expr Expr
  deriving (Eq, Show)

type Dict k d  =  [(k,d)]

define :: Dict k d -> k -> d -> Dict k d
define d s v = (s,v):d

find :: Eq k => Dict k d -> k -> Maybe d
find []             _                 =  Nothing
find ( (s,v) : ds ) name | name == s  =  Just v
                         | otherwise  =  find ds name

type EDict = Dict String Double
我研究了如何将+、-、和*传递到其他函数中,发现这些运算符是由以下定义定义的:

ghci> :t (*)
(*) :: (Num a) => a -> a -> a  
但是,当我运行代码时,会出现以下编译错误:

Illegal polymorphic or qualified type: Num a => a -> a -> a
    Perhaps you intended to use RankNTypes or Rank2Types
    In the type signature for ‘evalOp’:
      evalOp :: EDict
                -> ((Num a) => a -> a -> a) -> Expr -> Expr -> Maybe Double

我不确定为什么会发生这种情况,因为我给了我的函数Haskell定义的正确参数。任何帮助都将不胜感激,因为我对这门语言还很陌生

错误告诉您不能在函数链中的一个类型中嵌套类型限定符。而是将所有限定符放在类型签名的开头:

evalOp:: (Num a) => EDict -> (a -> a -> a) -> Expr -> Expr -> Maybe Double

请参阅以获得更深入的讨论。

现在,您的
Expr
数据类型被限制为
双值表达式,因此不需要处理多态性

evalOp:: EDict -> (Double -> Double -> Double) -> Expr -> Expr -> Maybe Double
evalOp d op x y =
  let r = eval d x
      s = eval d y
  in case (r, s) of
    (Just m, Just n) -> Just (m `op` n)
    _                -> Nothing
(+)::Num a=>a->a->a
evalOp
的有效参数,因为它的类型可以“限制”为
Double->Double->Double

> let f :: Double -> Double -> Double; f = (+)
> f 3 5
8.0

如果表达式类型是参数化的,则会在函数上设置一个
Num a
约束(不仅仅是涉及
a
的参数,因为在整个函数中都需要相同的
a


它将有助于提供
EDict
Expr
的定义。
evalOp
的类型可能过于笼统;无论是
evalOp::numa=>EDict->(a->a->a)-->Expr->Expr->maybound
还是
evalOp::EDict->(Double->Double->Double->Expr->Expr->maybound
都可能足够了。您不需要多态回调,因为
Expr
似乎不是多态的。已使用EDict和Expr的定义更新帖子。此外,这些函数需要同时适用于整数和双精度数,因此我不能将其转换为其中一个。它们目前不会,因为
Expr
本身不能保存整数值。小代码回顾:
evalOp
最好使用
liftA2 op(eval d x)(eval d y)
@4castle当然,但是对于不熟悉该语言的人来说,这可能有点高级。尝试这样做会导致以下错误:
无法将预期类型“Double”与实际类型“a”匹配。“a”是一个严格的类型变量,由evalOp::Num a=>EDict->(a->a->a)的类型签名绑定->Expr->Expr->src/Ex02可能加倍。hs:51:10
@code学徒你确定吗?我不知道
a->a->a
如何传递
Double
@pigworker。我确信这一更改将解决OP询问的错误。代码中很可能存在其他问题,这些问题在更改后会导致其他错误。@Jackengles您应该发布一个新问题。快速的解决方案是根本不使用多态类型。只要做
(Double->Double->Double)
而不是
(a->a->a)
。更“正确”的解决方案是使所有类型都具有多态性,包括
Expr
。人们的优点在于他们能够理解问题的背景。谢谢,这似乎解决了问题!