diff --git a/build.sbt b/build.sbt
index 03a88d4160a1e08c6c22af9af6ff50a7951f6700..e0078963c4fbed682e0a56579191e4580115fd1c 100644
--- a/build.sbt
+++ b/build.sbt
@@ -21,7 +21,8 @@ scalacOptions ++= Seq(
   "-Ywarn-unused:params",
   "-Ywarn-unused:patvars",
   "-Ywarn-unused:privates",
-  "-Ypatmat-exhaust-depth", "40"
+  "-Ypatmat-exhaust-depth", "40",
+  "-language:higherKinds",
 )
 
 resolvers += Resolver.sonatypeRepo("releases")
diff --git a/src/main/scala/traverse/Fuse.scala b/src/main/scala/traverse/Fuse.scala
new file mode 100644
index 0000000000000000000000000000000000000000..3f92ceea633403883cc7d831e2a3a3f57b5d9c5c
--- /dev/null
+++ b/src/main/scala/traverse/Fuse.scala
@@ -0,0 +1,42 @@
+object Fuse {
+  /* reduced to relevant parts */
+  trait Traverse[F[_]] {
+    def traverse[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]] =
+      sequence(map(fa)(f))
+    def sequence[G[_]:Applicative,A](fma: F[G[A]]): G[F[A]] =
+      traverse(fma)(ma => ma)
+      
+    def map[A,B](fa: F[A])(f: A => B): F[B] = ??? // exercise sheet
+
+    /* Exercise: implement fusing two traversal functions in one 
+       traversal using applicative products */
+    
+    def fuse[G[_],H[_],A,B](fa: F[A])(f: A => G[B], g: A => H[B])
+      (implicit G: Applicative[G],H: Applicative[H])
+      : (G[F[B]], H[F[B]]) = ???
+  }
+
+
+  /* reduced to relevant parts */
+  trait Applicative[F[_]] {
+    def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] =
+      apply(map(fa)(f.curried))(fb)
+
+    def apply[A,B](fab: F[A => B])(fa: F[A]): F[B] =
+      map2(fab, fa)(_(_))
+
+    def unit[A](a: => A): F[A]
+
+    def map[A,B](fa: F[A])(f: A => B): F[B] =
+      apply(unit(f))(fa)
+
+    def product[G[_]](G: Applicative[G]): Applicative[Lambda[x => (F[x], G[x])]] = {
+      val self = this
+      new Applicative[Lambda[x => (F[x], G[x])]]{
+        def unit[A](a: => A) = (self.unit(a), G.unit(a))
+        override def apply[A,B](fs: (F[A => B], G[A => B]))(p: (F[A], G[A])) =
+          (self.apply(fs._1)(p._1), G.apply(fs._2)(p._2))
+      }
+    }
+  }
+}
diff --git a/src/main/scala/traverse/SequenceMap.scala b/src/main/scala/traverse/SequenceMap.scala
new file mode 100644
index 0000000000000000000000000000000000000000..56577f7526e834dca485a66e7aa37b9184df4cb3
--- /dev/null
+++ b/src/main/scala/traverse/SequenceMap.scala
@@ -0,0 +1,28 @@
+object SequenceMap {
+  trait Applicative[F[_]] {
+    // Exercise: implement sequence for maps instead of lists
+    def sequenceMap[K,V](m: Map[K, F[V]]): F[Map[K,V]] = ???
+
+    //you can use any of these methods
+    def unit[A](a: => A): F[A]
+
+    def apply[A,B](fab: F[A => B])(fa: F[A]): F[B] = map2(fab, fa)((ab, a) => ab(a))
+
+    def map[A,B](fa: F[A])(f: A =>  B): F[B] = apply(unit(f))(fa)
+
+    def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) =>  C): F[C] =
+      apply(apply(unit(f.curried))(fa))(fb)
+
+    def map3[A,B,C,D](fa: F[A], fb: F[B], fc: F[C])(f: (A, B, C) =>  D): F[D] =
+      apply(apply(apply(unit(f.curried))(fa))(fb))(fc)
+
+    def factor[A,B](fa: F[A], fb: F[B]): F[(A,B)] =
+      map2(fa, fb)((_,_))
+
+    def sequence[A](fas: List[F[A]]): F[List[A]] =
+      fas.foldRight[F[List[A]]](unit(Nil))((a, b) => map2(a, b)(_::_))
+
+    def traverse[A,B](fas: List[A])(f: A => F[B]): F[List[B]] =
+      fas.foldRight[F[List[B]]](unit(Nil))((a, b) => map2(f(a), b)(_::_))
+  }
+}