2011-01-06 4 views
3

문자열을 키로 포함하고 일부 람다 함수를 항목으로 포함하는 하스켈 맵이 있습니다. 예 :람다 함수와 연산자를 연결하는 맵

-- 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)] 

는 I 입력으로 취하는 함수를 작성하고자 :

  • 오퍼레이터를 나타내는 캐릭터 [ "+", "-", "*", "/"] 연산자와 작전지도를 바탕으로
  • 두 숫자

는 기능/등 합계/뺄셈을 평가합니다. 두 숫자 중.

내가 좋아하는 뭔가를 시도했다 :

(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

'[("+", (+)), ("-",]'(괄호 안의 연산자는 섹션이라고 불리우며 람다와 똑같은 일을합니다.) 함수의 중온 응용 프로그램에 대해서도 작동하고 인수가 고정되어있을 때 (예 :'(\'mod \'2)'또는' (2 /)'). – delnan

+1

@delnan 그는'-'와'/'에 대한 논쟁을 통해 "틀린"방법으로 라운드를 할 수 있습니다. – dave4420

+0

@Dave : 예, 어리석은 나를. 여전히 명시적인 람다에 대한 필요는 없습니다 : flip (-)과 flip (/) : – delnan

답변

7

조회는 lookup :: Ord k => k -> Map k a -> 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에서 Either 또는 Maybe의 결과를 반환하여 키가 존재하지 않을 가능성을 수용 할 수도 있지만, 이는 사용자의 책임입니다. 다음과 같이

는 아마도 정의 :이 결과 값 또는 빈 값을 보유 중

입니다
data Maybe a = Just a | Nothing 

. 존재 론적 철학자처럼 하스켈은 Nothing의 가능성을 인정하도록 강요합니다.

+0

Andrei가'ops'를 정의하는 방식을 고려할 때, 섹션에 대해 조금 짚어 보겠습니다 :'flip (-)'과'flip (/)'이어야합니다. – dave4420

+0

오, 이상 하네, 네 말이 맞아. 나는 그들이 뒤집혔다는 것을 알지 못했다. 감사. – Bill

4

첫 번째로 보여 주신 오류는 표시 한 코드 때문이 아닙니다. 그 오류가 lookupMaybe 반환하는 사실에 의해 발생

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

: 코드는 (GHC)에 다음과 같은 오류가 발생합니다. 따라서 먼저 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 -> a -> a))를 Maybe a, 직접 a에 적용 할 수있는 방법이 없습니다. <*>을 사용하면 LHS를 mote에서 꺼내 RHS에 적용하고 다시 모나드에 삽입 할 수 있습니다. (또는 Bill을 수동으로 수행하십시오.)