2012-03-15 25 views
8

A menudo me resulta deseoso de insertar funciones regulares en una secuencia "enlazada". Como en este ejemplo artificial:Enlace de secuencia con funciones puras

getLine >>= lift (map toUpper) >>= putStrLn 

necesito para definir la función de elevación lift :: (a -> b) -> a -> m b para hacer este trabajo. El problema es que no sé de esa función, y Hoogle tampoco parece tenerla. Esto me parece extraño ya que esto tiene mucho sentido para mí.

Ahora, probablemente haya otras maneras de hacerlo funcionar, pero me gusta la forma en que el código de estilo sin puntos me permite escanear la línea en una pasada para descubrir qué está sucediendo.

let lift f x = return (f x) in 
getLine >>= lift (map toUpper) >>= putStrLn 

Mi pregunta se reduce a esto: me falta algo o cómo no hay una función como la elevación. Mi experiencia en Haskell todavía es muy limitada, así que supongo que la mayoría de las personas lo resuelve de una manera diferente. ¿Puede alguien explicarme la forma idiomática de resolver esto?

Respuesta

18

Hay tres formas idiomáticas.

  1. No utilice bind; utilizar el primer golpe a su búsqueda Hoogle lugar:

    liftM (map toUpper) getLine >>= putStrLn 
    

    Hay una variedad de grafías alternativas de liftM, como fmap o (<$>).

  2. Inline la función que define lift:

    getLine >>= return . map toUpper >>= putStrLn 
    
  3. Use las leyes de las mónadas para fusionar las dos últimas se une en la opción 2:

    getLine >>= putStrLn . map toUpper 
    
+1

pondría 'foo >> = regreso bar >> = baz' último en la lista. Está bien en cadenas más largas, pero en casos cortos como el ejemplo, 'foo >> = baz. bar' es mucho más legible IMO. –

+0

En realidad, creo 'foo >> = return. bar >> = baz' es una manera ordenada. No se me ocurrió que esa es realmente la función de elevación que estaba buscando. –

+4

'putStrLn. map toUpper = << getLine "se ve bastante limpio. Me gusta usar '= <<' ya que se asemeja a la aplicación de función. – danr

3

utilizar la instancia Functor en tales casos:

> import Data.Char 
> import Data.Functor 
> map toUpper <$> getLine >>= putStrLn 
foo 
FOO 
> 
Cuestiones relacionadas