【问题标题】:Map that associates operators with lambda functions将运算符与 lambda 函数相关联的映射
【发布时间】:2011-01-06 11:58:45
【问题描述】:

我有一个 Haskell Map,包含字符串作为键和一些 lambda 函数作为项目。 例如:

-- List of supported Operators -> mapping with functions
ops = Map.fromList [("+", \x y -> x + y),
                    ("-", \x y -> y - x),
                    ("*", \x y -> x * y),
                    ("/", \x y -> y / x)]

我想写一个函数作为输入:

  • 表示运算符 ["+", "-", "*", "/"] 的字符串
  • 两个数字

根据算子和操作图,该函数将计算和/减/等。两个数字中的一个。

我尝试过类似的方法:

(Map.lookup "+" a) 1 2

但它不起作用。

错误是:

Top level:
    No instance for (Show (Integer -> Integer))
      arising from use of `print' at Top level
    Probable fix: add an instance declaration for (Show (Integer
    In a 'do' expression: print it

<interactive>:1:1:
    No instance for (Monad ((->) t))
      arising from use of `Data.Map.lookup' at <interactive>:1:1-
    Probable fix: add an instance declaration for (Monad ((->) t)
    In the definition of `it': it = (Data.Map.lookup "+" a) 1 2

...对我不是很有帮助。

有什么建议吗?谢谢!

【问题讨论】:

  • 请注意,您可以只执行 [("+", (+)), ("-", (-)), ...] (括号中的运算符称为一个部分,并且与您的 lambda 更简洁地执行相同的操作;它也适用于函数的中缀应用,并且当任一参数为固定,例如(`mod` 2)(2/))。
  • @delnan 尽管他对-/ 提出异议,但这样做的“错误”方式。
  • @Dave:是的,我很傻。不过,不需要显式的 lambda:flip (-)flip (/) :)
  • 感谢您的回答。最终我听从了比尔的建议,一切都如我所愿。

标签: haskell lambda map


【解决方案1】:

查找的类型为lookup :: Ord k =&gt; k -&gt; Map k a -&gt; Maybe a。结果被包裹在 Maybe 中,表示该键可能不存在于地图中。

这是一种可行的方法:

runOp :: String -> a -> a -> b
runOp key x y = case lookup key ops of
                  Just op -> op x y
                  Nothing -> error ("Couldn't find operator: " ++ key)

如果密钥不存在,这将触底。您还可以从 runOp 返回 EitherMaybe 结果,以适应密钥不存在的可能性,但这取决于您。

可能定义如下:

data Maybe a = Just a | Nothing

也就是说,它要么保存一个结果值,要么保存一个空值。就像存在主义哲学家一样,Haskell 强迫你承认Nothing 的可能性。

【讨论】:

  • 我会省略有关部分的内容:鉴于 Andrei 定义 ops 的方式,它应该是 flip (-)flip (/)
  • 哦,奇怪,你是对的。我没有注意到它们被翻转了。谢谢。
【解决方案2】:

首先,您显示的错误不是由您显示的代码引起的。您的代码导致以下错误(在 ghc 中):

Couldn't match expected type `t1 -> t2 -> t'
against inferred type `Data.Maybe.Maybe

该错误是由lookup 返回Maybe 引起的。所以你需要先解开Maybe

【讨论】:

    【解决方案3】:
    import Control.Applicative
    
    ops :: (Fractional a) => Map.Map String (a -> a -> a)
    ops = Map.fromList [("+", (+)),
                        ("-", flip (-)),
                        ("*", (*)),
                        ("/", flip (/))]
    
    apply :: (Fractional a) => String -> a -> a -> Maybe a
    apply op x y = Map.lookup op ops <*> y <*> x
    

    因为lookup 返回一个Maybe a(好吧,在这种情况下是Maybe (a -&gt; a -&gt; a)),所以无法直接将它应用到a。我们可以使用&lt;*&gt; 将 LHS 从 mote 中拉出,将其应用于 RHS,然后将其注入 monad。 (或者像比尔一样手动完成。)

    【讨论】:

      猜你喜欢
      • 2020-07-03
      • 2019-04-21
      • 2022-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-09
      • 2016-01-26
      • 2017-08-30
      相关资源
      最近更新 更多