2011-12-21 11 views
8

Haskell tiene la función sumaCubesumming en Haskell

sum :: Num a => [a] -> a 

Cuál puede ser muy bien compuesta para resumir una matriz por

sum . map sum :: Num a => [[a]] -> a 

Profundizando, sin embargo, como la suma de un cubo, crea la restricción Num [a]

sum . map sum . map sum :: (Num a, Num [a]) => [[[a]]] -> a 

Que, si lo piensas bien, es natural. Entonces, con el intento anterior de definir la función sumcube explotando en la cara, necesitamos encontrar una ruta diferente. Uno de estos intentos sería:

sum . map sum . map (map sum) :: Num a => [[[a]]] -> a 

Lo que no parece ser tan natural como la función summatrix.

En mi búsqueda de la posesión de herramientas mentales para la resolución de problemas en Haskell, estoy interesado en saber cómo abordar este problema de sumar una estructura de cualquier profundidad, por ejemplo, apilando map sum como en mi tercer ejemplo de código. ¿Es esto posible? Y en ese caso, ¿cómo lo harías?

+0

¿Usted intentó 'suma. mapa (suma del mapa) '? – fuz

+0

sum. map (map sum) :: (Num [b], Num b) => [[[b]]] -> [b] –

+0

Si está interesado en operaciones rápidas en matrices numéricas, probablemente debería usar vector, repa, hmatrix, o paquetes similares. –

Respuesta

12

Tendrás que trabajar desde adentro hacia afuera. Cuando tiene una función f para sumar una estructura de datos, entonces sum . map f es la forma de sumar una lista de esas estructuras de datos.

     sum :: Num a => [a] -> a 
      sum . map sum :: Num a => [[a]] -> a 
sum . map (sum . map sum) :: Num a => [[[a]]] -> a 
+0

que es una buena manera de verlo –

+0

Elijo esto como mi respuesta aceptada porque explica el problema de la mejor manera. –

0

En primer lugar, está Template Haskell (aunque la extensión GHC). O usted podría utilizar un data que apoya la lista de profundidad arbitraria anidación así:

data Tree a = Leaf a | Node [Tree a] 

sumTree (Leaf x) = x 
sumTree (Node xs) = (sum . map sumTree) xs 

main = print $ sumTree $ Node [ Node [Leaf 3, Leaf 4, Leaf 5] 
           , Node [Leaf 1, Leaf 4, Leaf 2]] 

que imprimirá 19 aquí. Sin embargo, esto no garantiza que todas las hojas tengan la misma profundidad de anidamiento y no sé cómo construir esto a partir de las listas.

5

Quizás esto? Asume asociatividad, pero agregar nueva capa es simple

sum . concat . concat :: Num c => [[[c]]] -> c 
+0

Concat fue realmente mi motivación para la pregunta.Concat compone maravillosamente qué suma no, supongo porque suma tiene una restricción de tipo. Punto a favor. –

+2

'concat' elimina capas del exterior del tipo, mientras que' sum' tiene que eliminar capas del interior. Contraste 'concat. concat' y 'sum. map sum' con 'concat. mapa concat' – dave4420

+1

@MagnusKronqvist: La diferencia es que 'concat' opera completamente en las listas, mientras que' sum' opera en los elementos. Con este último siempre debe comenzar con la lista más interna, pero cualquier "lista de listas" puede concatenarse. Este es el concepto fundamental detrás de que las listas sean una mónada, por cierto. –

14

¿Qué tal tipo de clases?

class Summable a where 
    total :: a -> Int 

instance Summable Int where 
    total = id 

instance Summable x => Summable [x] where 
    total = sum . map total 

total ([[[1,2,3],[4,5]],[[6],[7,8,9,10]]] :: [[[Int]]]) 
--55 
+0

¡Maldito, me ganaste! –

+0

aspecto interesante de hecho. Se escala muy bien –

+1

realmente agradable - lamentablemente no puedo responder a las preguntas favoritas - este es un concepto que quiero tener en cuenta. – epsilonhalbe

1

Parece más natural para mí para definir de sum en cuanto a la dimensión anterior sum una dimensión adicional.

-- given sum :: Num a => [a] -> a 

sum2 :: [[a]] -> a 
sum2 = sum . map sum 

sum3 :: [[[a]]] -> a 
sum3 = sum . map sum2 

sum4 :: [[[[a]]]] -> a 
sum4 = sum . map sum3 

Esto es básicamente la misma idea que lo que dijo Sjoerd. Si desea utilizar solamente map y sumy no Refactor subexpresiones comunes en nombres útiles ... a continuación, utilizar el razonamiento ecuacional para reemplazar las funciones personalizadas sum2, sum3, etc.