 extension ModuleHom where X: FreeModuleType, Y: FreeModuleType {
     public static func linearlyExtend(_ f: @escaping (X.Generator) -> Codomain) -> ModuleHom<X, Y> {
         return ModuleHom { (m: Domain) in
-            m.elements.map{ (a, r) in r * f(a) }.sumAll()
+            m.decomposed().sum { (a, r) in r * f(a) }
         }
     }
     

        return FreeModule(sum)
    }
    
    public func mapGenerators<A2>(_ f: (A) -> A2) -> FreeModule<A2, R> {
        return FreeModule<A2, R>(elements.mapKeys(f))
    }
    
    public func mapComponents<R2>(_ f: (R) -> R2) -> FreeModule<A, R2> {
        return FreeModule<A, R2>(elements.mapValues(f))
    }
    
    public var description: String {
        return Format.terms("+", generators.map { a in (self[a], a.description, 1) })
    }


public protocol FreeModuleType: Module {
    associatedtype Generator: FreeModuleGenerator
    static func wrap(_ a: Generator) -> Self
    static func combine<n>(generators: [Generator], vector: ColVector<n, CoeffRing>) -> Self
    func factorize(by: [Generator]) -> DVector<CoeffRing>
    func decomposed() -> [(Generator, CoeffRing)]
}

public struct FreeModule<A: FreeModuleGenerator, R: Ring>: FreeModuleType {
    public typealias CoeffRing = R
    public typealias Generator = A
    
    private let elements: [A: R]
    
    // root initializer
    public init(_ elements: [A : R]) {
