2012-02-29 47 views
13

Có sự khác biệt nào giữa hai chức năng này không?Haskell: Sự khác nhau giữa (+1) và ( x-> x + 1) là gì?

ghct nói:

Prelude> :t (+1) 
(+1) :: Num a => a -> a 
Prelude> :t \x->x+1 
\x->x+1 :: Num a => a -> a 

Nhưng

Khi tôi sử dụng (1) cú pháp trong đoạn mã này:

data B = B { 
    pos :: Int, 
    cells :: [Int] 
} deriving (Show) 

createB :: Int -> B 
createB n = B 0 (take n $ repeat 0) 

size :: B -> Int 
size b = length $ cells b 

get_curr :: B -> Int 
get_curr b = (cells b) !! (pos b) 

apply :: (Int -> Int) -> B -> B 
apply f b = let n = pos b 
       h = take n $ cells b  -- head 
       t = drop (n + 1) $ cells b -- tail 
       in B n $ h ++ [f (get_curr b)] ++ t 

-- ... 
eval :: [Char] -> StateT B IO() 
eval [] = return() 
eval (x:xs) = do 
       b <- get 

       put $ case x of 
         '+'   -> apply (+1) b 
         '-'   -> apply (-1) b 
         '>'   -> fwd b 
         '<'   -> back b 
         otherwise -> b 
       -- ... 

khúc dạo đầu (cũng như trình biên dịch) cho biết :

> :load BrainFuck.hs 
[1 of 1] Compiling BrainFuck  (BrainFuck.hs, interpreted) 

BrainFuck.hs:49:40: 
    No instance for (Num (Int -> Int)) 
     arising from the literal `1' 
    Possible fix: add an instance declaration for (Num (Int -> Int)) 
    In the expression: 1 
    In the first argument of `apply', namely `(- 1)' 
    In the expression: apply (- 1) b 
Failed, modules loaded: none. 

Tôi đang làm gì sai? xin lỗi nếu mã không-để-mát (nguồn đầy đủ ở đây: https://github.com/nskeip/bf/blob/a755b2d27292593d63fe1e63c2a6e01cebc73520/BrainFuck.hs)

Trả lời

22

Mã này:

(-1) 

... không có nghĩa là điều tương tự như mã này:

\ x -> x - 1 

- là một trường hợp đặc biệt trong Haskell; nó chỉ là toán tử tiền tố duy nhất bằng ngôn ngữ. Khi bạn viết (-1), bạn nhận được "số âm", một số và không phải là "trừ một" là một hàm.

Bạn nên sử dụng subtract 1 để nhận những gì bạn cần.

+4

Bạn cũng có thể sử dụng 'pred', nhưng lưu ý rằng' pred minBound' sẽ ném một ngoại lệ trong khi 'trừ 1 minBound' sẽ bao quanh. – hammar

11

Vấn đề của bạn không phải là với (+1), đó là với (-1):

Prelude> :t (-1) 
(-1) :: Num a => a 

-1 is a number! Hãy thử với apply (\x -> x-1) b hoặc apply (subtract 1) b.

+0

chết tiệt! chính xác) nhưng tại sao (+1) không phải là?))) –

+0

Bởi vì bạn không * cần * một tiền tố/tiền tố '+' và do đó không có. – delnan

+0

Xem liên kết đến "Phần của toán tử kết hợp" – Joni

4

Không có sự khác biệt giữa (+1)\x -> x + 1 và nếu bạn nhìn kỹ, (+1) không phải là những gì gây ra lỗi lầm của mình. (-1) là. Và đó là bởi vì không giống như (+1), (-1) không phải là một phần của nhà điều hành, đó là phần phủ định.

4

Thay vì subtract biểu thức giảm có thể được viết trực tiếp cũng như (+(-1)).

Các vấn đề liên quan