2012-02-29 23 views
13

¿Hay alguna diferencia entre estas dos funciones?Haskell: ¿Cuál es la diferencia entre (+1) y ( x-> x + 1)?

ghct dice:

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

Pero

Cuando yo (1) sintaxis en este pedazo de código:

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

preludio (así como compilador) dijo :

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

¿Qué estoy haciendo mal? lo siento si el código no es tan fría (fuente completo aquí: https://github.com/nskeip/bf/blob/a755b2d27292593d63fe1e63c2a6e01cebc73520/BrainFuck.hs)

Respuesta

22

este código:

(-1) 

... no significa lo mismo que este código:

\ x -> x - 1 

- es un caso especial en Haskell; es el único operador de prefijo en el idioma. Cuando escribe (-1), obtiene "uno negativo" que es un número, y no "resta uno", que es una función.

Debe usar subtract 1 para obtener lo que necesita.

+4

También puede usar 'pred', pero tenga en cuenta que' pred minBound' emitirá una excepción mientras que 'restar 1 minBound' se ajustará. – hammar

11

Su problema no es con (+1), es con (-1):

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

-1 is a number! intento con apply (\x -> x-1) b o apply (subtract 1) b.

+0

maldición! exactamente) pero ¿por qué (+1) no es?))) –

+0

Porque no * necesita * unary/prefijo '+' y por lo tanto no hay ninguno. – delnan

+0

Consulte el enlace a "Sección de un operador de infijo" – Joni

4

No hay diferencia entre (+1) y \x -> x + 1 y si mira de cerca, (+1) no es lo que está causando su error. (-1) es. Y eso es porque a diferencia de (+1), (-1) no es una sección de operador, es negativa.

4

En lugar de subtract la expresión de decremento se puede escribir directamente también como (+(-1)).

Cuestiones relacionadas