2011-01-06 41 views
3

我有一個Haskell映射,包含字符串作爲鍵和一些lambda函數作爲項。 例如:將運營商與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)] 

我想要寫一個函數,它作爲輸入:

  • 表示操作者的字符串[ 「+」, 「 - 」, 「*」, 「/」]
  • 兩個數字

基於運營商和OPS映射,函數將計算總和/減法/等。這兩個數字。

我已經試過類似:

(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 

...對我來說不是非常有幫助。

有什麼建議嗎?謝謝 !

+4

請注意,您可以執行`[(「+」,(+)),(「 - 」,( - )),...](parens中的操作符被稱爲section,並且與你的lambdas更加整齊地做同樣的事情;它也適用於函數的中綴應用,並且當任一參數是固定的,例如`(\`mod \`2)`或' (2 /)`)。 – delnan 2011-01-06 12:15:44

+1

@delnan雖然他有`-`和`/`這樣的「錯誤」方法。 – dave4420 2011-01-06 12:57:12

回答

7

查找類型爲lookup :: Ord k => k -> Map k a -> Maybe a。結果被封裝在一個可能中,以表明密鑰可能不在地圖中。

這裏有一個辦法做到這一點,將工作:

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 

也就是說,它可夾持一結果值或空值。像一個存在主義的哲學家一樣,哈斯克爾強迫你承認Nothing的可能性。

4

首先,您顯示的錯誤不是由您顯示的代碼引起的。您的代碼將導致以下錯誤(在GHC):

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

該錯誤是由事實lookup返回Maybe引起的。所以你首先需要拆開Maybe

2
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 -> a -> a)在這種情況下),沒有辦法直接把它應用到一個a。我們可以使用<*>將LHS拉出微粒,將其應用於RHS,並將其注入到monad中。 (或者像Bill一樣手動操作)。