por - pattern matching haskell
¿Alimentar elementos de una tupla a una función como argumentos en Haskell? (3)
La función uncurry
convierte una función de dos argumentos (al curry) en una función en pares. Aquí está su tipo de firma:
uncurry :: (a -> b -> c) -> (a, b) -> c
Necesitas usarlo en printf
, así:
mapM_ (uncurry $ printf "Values: %d %d/n") [(1,100),(2,350),(3,600),(4,200)]
Otra solución es utilizar la coincidencia de patrones para deconstruir la tupla, como esto:
mapM_ (/(a,b) -> printf "Values: %d %d/n" a b) [(1,100),(2,350),(3,600),(4,200)]
En mi programa Haskell, quiero usar printf para formatear una lista de tuplas. Puedo asignar printf sobre una lista para imprimir los valores uno por uno como este:
mapM_ (printf "Value: %d/n") [1,2,3,4]
Value: 1
Value: 2
Value: 3
Value: 4
Quiero poder hacer algo como esto:
mapM_ (printf "Values: %d %d/n") [(1,100),(2,350),(3,600),(4,200)]
Values: 1 100
Values: 2 350
Values: 3 600
Values: 4 200
Pero esto pasa una tupla a printf, no dos valores separados. ¿Cómo puedo convertir la tupla en dos argumentos para printf?
Una alternativa segura para el Text.Printf
a Text.Printf
es el paquete de formatting . Text.Printf.printf
no garantiza en tiempo de compilación que el número de parámetros de formato se alinee con el número de argumentos y sus tipos. Lea el artículo de Chris Done, ¿Qué hay de malo con printf? por ejemplo.
Un ejemplo de uso:
{-# LANGUAGE OverloadedStrings #-}
import Formatting
map (uncurry $ formatToString ("Value: " % int % " " % int)) [(1,100), (2,350), ...]
map (/(x,y) -> formatToString ("Value: " % int % " " % int) x y) [(1,100), (2,350), ...]
Requiere que la extensión GHC OverloadedStrings funcione correctamente.
Si bien formatToString ("Value: " % int % " " % int)
tiene el tipo Int -> Int -> String
, el sistema no está en curso y da el tipo (Int, Int) -> String
cuyo tipo de entrada coincide con los elementos de la lista .
El proceso de reescritura se puede desglosar; asumiendo f
= formatString ("Value: " ...)
,
map (/(x,y) -> f x y) ≡ map (/(x,y) -> uncurry f (x,y)) ≡ map (uncurry f)
Es decir, primero debe desbloquear f para lograr la función que acepta tuplas, y luego debe realizar una Eta-conversion normal ya que /(x,y) -> uncurry f (x,y)
es equivalente a simplemente uncurry f
. Para imprimir cada línea en el resultado, use mapM_
:
mapM_ (putStrLn . uncurry $ formatToString ...) [(1,100), (2,350), ...]
Si ejecuta hlint YourFile.hs , se le recomendarán estas reescrituras.
mapM_ (/(x,y) -> printf "Value: %d %d/n" x y) [(1,100),(2,350),(3,600),(4,200)]