2012-02-29 3 views
13

Есть ли разница между этими двумя функциями?Haskell: В чем разница между (+1) и ( x-> x + 1)?

ghct говорит:

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

Но

Когда я использовал (+1) синтаксис в этом фрагменте кода:

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 
       -- ... 

прелюдии (а также компилятор) сказал :

> :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. 

Что я делаю неправильно? жаль, если код не так круто (полный источник здесь: https://github.com/nskeip/bf/blob/a755b2d27292593d63fe1e63c2a6e01cebc73520/BrainFuck.hs)

ответ

22

Этот код:

(-1) 

... не означает, что то же самое, как этот код:

\ x -> x - 1 

- является частным случаем в Haskell; он является единственным оператором на этом языке. Когда вы пишете (-1), вы получаете «отрицательный», который является числом, а не «вычитать один», который является функцией.

Чтобы получить то, что вам нужно, вы должны использовать subtract 1.

+4

Вы также можете использовать 'pred', но обратите внимание, что' pred minBound' будет генерировать исключение, в то время как 'subtract 1 minBound' будет обтекать. – hammar

11

Ваша проблема не с (+1), это с (-1):

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

-1 is a number! Попробуйте с apply (\x -> x-1) b или apply (subtract 1) b.

+0

черт побери! точно), но почему (+1) нет?))) –

+0

Потому что вы не * нуждаетесь * унарный/префикс '+' и, следовательно, его нет. – delnan

+0

См. Ссылку на «Раздел инфиксного оператора» – Joni

4

Нет никакой разницы между (+1) и \x -> x + 1, и если вы посмотрите внимательно, то (+1) не является причиной вашей ошибки. (-1) есть. И это потому, что в отличие от (+1), (-1) не является секцией оператора, она отрицательная.

4

Вместо subtract выражение декремента может быть записано также как (+(-1)).

Смежные вопросы