diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Marco Zocca (c) 2017
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Marco Zocca nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,34 @@
+# matrix-market-attoparsec
+
+[![Build Status](https://travis-ci.org/ocramz/matrix-market-attoparsec.png)](https://travis-ci.org/ocramz/matrix-market-attoparsec)
+
+Attoparsec parser for the NIST Matrix Market format [1].
+
+The library also contains functions for serializing to text file, and the read/write/read roundtrip works as expected.
+
+## User guide
+
+The module `Data.Matrix.MatrixMarket` exports the user interface:
+
+
+    readMatrix :: FilePath -> IO (Matrix S.Scientific)
+
+    readArray :: FilePath -> IO (Array S.Scientific)
+
+    writeMatrix :: Show a => FilePath -> Matrix a -> IO ()
+ 
+    writeArray :: Show a => FilePath -> Array a -> IO ()  
+
+The first two functions contain the parsing logic, and make use of `scientific` for parsing numerical data in scientific notation.
+
+`test/LibSpec.hs` contains a simple read/write/read sanity test:
+
+    m0 <- readMatrix fname   -- load original
+    writeMatrix ftemp m0     -- save as temp
+    m1 <- readMatrix ftemp   -- load temp
+    m0 `shouldBe` m1         -- compare temp with original
+
+
+## References
+
+[1] [http://math.nist.gov/MatrixMarket/](http://math.nist.gov/MatrixMarket/)
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/data/fidapm05.mtx b/data/fidapm05.mtx
new file mode 100644
--- /dev/null
+++ b/data/fidapm05.mtx
@@ -0,0 +1,522 @@
+%%MatrixMarket matrix coordinate real general
+42 42 520
+1 1  1.9555555555555e+00
+2 1 -1.9999999999999e-01
+10 1 -1.0666666666667e+00
+11 1 -3.5555555555556e-01
+19 1  1.3322676295502e-15
+20 1  1.1111111111111e-01
+25 1  1.3333333333333e-01
+26 1  4.4444444444444e-03
+27 1  1.3333333333333e-02
+1 2 -1.9999999999999e-01
+2 2  1.2444444444444e+00
+3 2 -2.0000000000001e-01
+4 2 -3.3333333333334e-02
+10 2 -3.5555555555555e-01
+11 2 -4.0000000000000e-01
+12 2 -3.5555555555555e-01
+13 2  1.1111111111111e-01
+19 2  1.1111111111111e-01
+20 2 -6.6666666666669e-02
+21 2  1.1111111111111e-01
+22 2 -2.2222222222222e-02
+25 2  3.3333333333333e-02
+26 2  1.1111111111111e-03
+27 2  6.6666666666666e-03
+28 2  3.3333333333334e-02
+29 2  1.1111111111111e-03
+30 2  6.6666666666669e-03
+2 3 -2.0000000000001e-01
+3 3  1.9555555555555e+00
+4 3 -1.9999999999999e-01
+11 3 -3.5555555555555e-01
+12 3 -1.0666666666667e+00
+13 3 -3.5555555555556e-01
+20 3  1.1111111111111e-01
+21 3  3.5527136788005e-15
+22 3  1.1111111111111e-01
+28 3  1.3333333333333e-01
+29 3  4.4444444444444e-03
+30 3  4.0000000000000e-02
+2 4 -3.3333333333334e-02
+3 4 -1.9999999999999e-01
+4 4  1.2444444444444e+00
+5 4 -2.0000000000001e-01
+6 4 -3.3333333333337e-02
+11 4  1.1111111111111e-01
+12 4 -3.5555555555554e-01
+13 4 -4.0000000000000e-01
+14 4 -3.5555555555555e-01
+15 4  1.1111111111112e-01
+20 4 -2.2222222222222e-02
+21 4  1.1111111111111e-01
+22 4 -6.6666666666664e-02
+23 4  1.1111111111111e-01
+24 4 -2.2222222222223e-02
+28 4  3.3333333333331e-02
+29 4  1.1111111111111e-03
+30 4  1.3333333333333e-02
+31 4  3.3333333333334e-02
+32 4  1.1111111111111e-03
+33 4  1.3333333333334e-02
+4 5 -2.0000000000001e-01
+5 5  1.9555555555555e+00
+6 5 -1.9999999999997e-01
+13 5 -3.5555555555555e-01
+14 5 -1.0666666666667e+00
+15 5 -3.5555555555557e-01
+22 5  1.1111111111111e-01
+23 5  7.5495165674511e-15
+24 5  1.1111111111111e-01
+31 5  1.3333333333333e-01
+32 5  4.4444444444444e-03
+33 5  6.6666666666666e-02
+4 6 -3.3333333333337e-02
+5 6 -1.9999999999997e-01
+6 6  1.2444444444445e+00
+7 6 -2.0000000000003e-01
+8 6 -3.3333333333331e-02
+13 6  1.1111111111111e-01
+14 6 -3.5555555555555e-01
+15 6 -4.0000000000001e-01
+16 6 -3.5555555555554e-01
+17 6  1.1111111111111e-01
+22 6 -2.2222222222223e-02
+23 6  1.1111111111111e-01
+24 6 -6.6666666666670e-02
+31 6  3.3333333333334e-02
+32 6  1.1111111111111e-03
+33 6  2.0000000000000e-02
+34 6  3.3333333333332e-02
+35 6  1.1111111111110e-03
+36 6  1.9999999999999e-02
+40 6  1.1111111111111e-01
+41 6 -2.2222222222222e-02
+6 7 -2.0000000000003e-01
+7 7  1.9555555555555e+00
+8 7 -1.9999999999998e-01
+15 7 -3.5555555555554e-01
+16 7 -1.0666666666666e+00
+17 7 -3.5555555555554e-01
+24 7  1.1111111111110e-01
+34 7  1.3333333333333e-01
+35 7  4.4444444444444e-03
+36 7  9.3333333333331e-02
+40 7 -6.6613381477509e-15
+41 7  1.1111111111112e-01
+6 8 -3.3333333333331e-02
+7 8 -1.9999999999998e-01
+8 8  1.2444444444445e+00
+9 8 -2.0000000000005e-01
+15 8  1.1111111111111e-01
+16 8 -3.5555555555558e-01
+17 8 -3.9999999999998e-01
+18 8 -3.5555555555556e-01
+24 8 -2.2222222222222e-02
+34 8  3.3333333333333e-02
+35 8  1.1111111111112e-03
+36 8  2.6666666666666e-02
+37 8  3.3333333333334e-02
+38 8  1.1111111111111e-03
+39 8  2.6666666666667e-02
+40 8  1.1111111111111e-01
+41 8 -6.6666666666668e-02
+42 8  1.1111111111111e-01
+8 9 -2.0000000000005e-01
+9 9  1.9555555555556e+00
+17 9 -3.5555555555552e-01
+18 9 -1.0666666666667e+00
+37 9  1.3333333333333e-01
+38 9  4.4444444444443e-03
+39 9  1.2000000000000e-01
+41 9  1.1111111111111e-01
+42 9  3.1086244689504e-15
+1 10 -1.0666666666667e+00
+2 10 -3.5555555555555e-01
+10 10  5.6888888888889e+00
+11 10 -1.0666666666667e+00
+19 10 -1.0666666666667e+00
+20 10 -3.5555555555555e-01
+25 10  1.1102230246252e-16
+26 10  1.7777777777778e-02
+27 10  1.3877787807814e-17
+1 11 -3.5555555555556e-01
+2 11 -4.0000000000000e-01
+3 11 -3.5555555555555e-01
+4 11  1.1111111111111e-01
+10 11 -1.0666666666667e+00
+11 11  3.9111111111110e+00
+12 11 -1.0666666666666e+00
+13 11 -5.3290705182007e-15
+19 11 -3.5555555555555e-01
+20 11 -3.9999999999999e-01
+21 11 -3.5555555555555e-01
+22 11  1.1111111111111e-01
+26 11  4.4444444444443e-03
+27 11  5.5511151231258e-17
+28 11  5.5511151231258e-17
+29 11  4.4444444444446e-03
+30 11 -3.4694469519536e-17
+2 12 -3.5555555555555e-01
+3 12 -1.0666666666667e+00
+4 12 -3.5555555555554e-01
+11 12 -1.0666666666666e+00
+12 12  5.6888888888888e+00
+13 12 -1.0666666666667e+00
+20 12 -3.5555555555555e-01
+21 12 -1.0666666666667e+00
+22 12 -3.5555555555555e-01
+28 12  2.2204460492503e-16
+29 12  1.7777777777778e-02
+30 12  1.9428902930940e-16
+2 13  1.1111111111111e-01
+3 13 -3.5555555555556e-01
+4 13 -4.0000000000000e-01
+5 13 -3.5555555555555e-01
+6 13  1.1111111111111e-01
+11 13 -5.3290705182007e-15
+12 13 -1.0666666666667e+00
+13 13  3.9111111111111e+00
+14 13 -1.0666666666667e+00
+15 13 -2.6645352591004e-15
+20 13  1.1111111111111e-01
+21 13 -3.5555555555556e-01
+22 13 -3.9999999999999e-01
+23 13 -3.5555555555555e-01
+24 13  1.1111111111111e-01
+28 13  2.2204460492503e-16
+29 13  4.4444444444443e-03
+30 13  1.6653345369377e-16
+31 13  1.1102230246252e-16
+32 13  4.4444444444446e-03
+33 13  6.9388939039072e-17
+4 14 -3.5555555555555e-01
+5 14 -1.0666666666667e+00
+6 14 -3.5555555555555e-01
+13 14 -1.0666666666667e+00
+14 14  5.6888888888888e+00
+15 14 -1.0666666666666e+00
+22 14 -3.5555555555555e-01
+23 14 -1.0666666666667e+00
+24 14 -3.5555555555554e-01
+31 14 -7.7715611723761e-16
+32 14  1.7777777777778e-02
+33 14 -1.6653345369377e-16
+4 15  1.1111111111112e-01
+5 15 -3.5555555555557e-01
+6 15 -4.0000000000001e-01
+7 15 -3.5555555555554e-01
+8 15  1.1111111111111e-01
+13 15 -2.6645352591004e-15
+14 15 -1.0666666666666e+00
+15 15  3.9111111111110e+00
+16 15 -1.0666666666667e+00
+22 15  1.1111111111112e-01
+23 15 -3.5555555555557e-01
+24 15 -3.9999999999999e-01
+31 15  4.4408920985006e-16
+32 15  4.4444444444444e-03
+34 15 -4.7184478546569e-16
+35 15  4.4444444444444e-03
+36 15 -3.1918911957973e-16
+40 15 -3.5555555555555e-01
+41 15  1.1111111111111e-01
+6 16 -3.5555555555554e-01
+7 16 -1.0666666666666e+00
+8 16 -3.5555555555558e-01
+15 16 -1.0666666666667e+00
+16 16  5.6888888888888e+00
+17 16 -1.0666666666667e+00
+24 16 -3.5555555555553e-01
+35 16  1.7777777777777e-02
+36 16  3.8857805861880e-16
+40 16 -1.0666666666666e+00
+41 16 -3.5555555555558e-01
+6 17  1.1111111111111e-01
+7 17 -3.5555555555554e-01
+8 17 -3.9999999999998e-01
+9 17 -3.5555555555552e-01
+16 17 -1.0666666666667e+00
+17 17  3.9111111111111e+00
+18 17 -1.0666666666667e+00
+24 17  1.1111111111111e-01
+34 17 -2.2204460492503e-16
+35 17  4.4444444444441e-03
+36 17 -2.2204460492503e-16
+37 17 -1.3877787807815e-16
+38 17  4.4444444444448e-03
+39 17 -2.7755575615629e-16
+40 17 -3.5555555555553e-01
+41 17 -3.9999999999997e-01
+42 17 -3.5555555555551e-01
+8 18 -3.5555555555556e-01
+9 18 -1.0666666666667e+00
+17 18 -1.0666666666667e+00
+18 18  5.6888888888888e+00
+37 18 -6.6613381477509e-16
+38 18  1.7777777777778e-02
+39 18 -3.3306690738755e-16
+41 18 -3.5555555555555e-01
+42 18 -1.0666666666667e+00
+1 19  1.3322676295502e-15
+2 19  1.1111111111111e-01
+10 19 -1.0666666666667e+00
+11 19 -3.5555555555555e-01
+19 19  1.9555555555556e+00
+20 19 -2.0000000000000e-01
+25 19 -1.3333333333333e-01
+26 19 -2.2222222222222e-02
+27 19 -1.3333333333333e-02
+1 20  1.1111111111111e-01
+2 20 -6.6666666666669e-02
+3 20  1.1111111111111e-01
+4 20 -2.2222222222222e-02
+10 20 -3.5555555555555e-01
+11 20 -3.9999999999999e-01
+12 20 -3.5555555555555e-01
+13 20  1.1111111111111e-01
+19 20 -2.0000000000000e-01
+20 20  1.2444444444444e+00
+21 20 -2.0000000000001e-01
+22 20 -3.3333333333331e-02
+25 20 -3.3333333333334e-02
+26 20 -5.5555555555556e-03
+27 20 -6.6666666666667e-03
+28 20 -3.3333333333334e-02
+29 20 -5.5555555555557e-03
+30 20 -6.6666666666669e-03
+2 21  1.1111111111111e-01
+3 21  3.5527136788005e-15
+4 21  1.1111111111111e-01
+11 21 -3.5555555555555e-01
+12 21 -1.0666666666667e+00
+13 21 -3.5555555555556e-01
+20 21 -2.0000000000001e-01
+21 21  1.9555555555556e+00
+22 21 -2.0000000000000e-01
+28 21 -1.3333333333333e-01
+29 21 -2.2222222222222e-02
+30 21 -4.0000000000000e-02
+2 22 -2.2222222222222e-02
+3 22  1.1111111111111e-01
+4 22 -6.6666666666664e-02
+5 22  1.1111111111111e-01
+6 22 -2.2222222222223e-02
+11 22  1.1111111111111e-01
+12 22 -3.5555555555555e-01
+13 22 -3.9999999999999e-01
+14 22 -3.5555555555555e-01
+15 22  1.1111111111112e-01
+20 22 -3.3333333333331e-02
+21 22 -2.0000000000000e-01
+22 22  1.2444444444444e+00
+23 22 -2.0000000000001e-01
+24 22 -3.3333333333335e-02
+28 22 -3.3333333333332e-02
+29 22 -5.5555555555553e-03
+30 22 -1.3333333333333e-02
+31 22 -3.3333333333334e-02
+32 22 -5.5555555555556e-03
+33 22 -1.3333333333333e-02
+4 23  1.1111111111111e-01
+5 23  7.5495165674511e-15
+6 23  1.1111111111111e-01
+13 23 -3.5555555555555e-01
+14 23 -1.0666666666667e+00
+15 23 -3.5555555555557e-01
+22 23 -2.0000000000001e-01
+23 23  1.9555555555555e+00
+24 23 -1.9999999999998e-01
+31 23 -1.3333333333333e-01
+32 23 -2.2222222222222e-02
+33 23 -6.6666666666667e-02
+4 24 -2.2222222222223e-02
+5 24  1.1111111111111e-01
+6 24 -6.6666666666670e-02
+7 24  1.1111111111110e-01
+8 24 -2.2222222222222e-02
+13 24  1.1111111111111e-01
+14 24 -3.5555555555554e-01
+15 24 -3.9999999999999e-01
+16 24 -3.5555555555553e-01
+17 24  1.1111111111111e-01
+22 24 -3.3333333333335e-02
+23 24 -1.9999999999998e-01
+24 24  1.2444444444444e+00
+31 24 -3.3333333333334e-02
+32 24 -5.5555555555556e-03
+33 24 -2.0000000000000e-02
+34 24 -3.3333333333331e-02
+35 24 -5.5555555555552e-03
+36 24 -1.9999999999999e-02
+40 24 -2.0000000000004e-01
+41 24 -3.3333333333329e-02
+1 25  1.3333333333333e-01
+2 25  3.3333333333333e-02
+10 25  1.1102230246252e-16
+19 25 -1.3333333333333e-01
+20 25 -3.3333333333334e-02
+25 25  0.0000000000000e+00
+1 26  4.4444444444444e-03
+2 26  1.1111111111111e-03
+10 26  1.7777777777778e-02
+11 26  4.4444444444443e-03
+19 26 -2.2222222222222e-02
+20 26 -5.5555555555556e-03
+26 26  0.0000000000000e+00
+1 27  1.3333333333333e-02
+2 27  6.6666666666666e-03
+10 27  1.3877787807814e-17
+11 27  5.5511151231258e-17
+19 27 -1.3333333333333e-02
+20 27 -6.6666666666667e-03
+27 27  0.0000000000000e+00
+2 28  3.3333333333334e-02
+3 28  1.3333333333333e-01
+4 28  3.3333333333331e-02
+11 28  5.5511151231258e-17
+12 28  2.2204460492503e-16
+13 28  2.2204460492503e-16
+20 28 -3.3333333333334e-02
+21 28 -1.3333333333333e-01
+22 28 -3.3333333333332e-02
+28 28  0.0000000000000e+00
+2 29  1.1111111111111e-03
+3 29  4.4444444444444e-03
+4 29  1.1111111111111e-03
+11 29  4.4444444444446e-03
+12 29  1.7777777777778e-02
+13 29  4.4444444444443e-03
+20 29 -5.5555555555557e-03
+21 29 -2.2222222222222e-02
+22 29 -5.5555555555553e-03
+29 29  0.0000000000000e+00
+2 30  6.6666666666669e-03
+3 30  4.0000000000000e-02
+4 30  1.3333333333333e-02
+11 30 -3.4694469519536e-17
+12 30  1.9428902930940e-16
+13 30  1.6653345369377e-16
+20 30 -6.6666666666669e-03
+21 30 -4.0000000000000e-02
+22 30 -1.3333333333333e-02
+30 30  0.0000000000000e+00
+4 31  3.3333333333334e-02
+5 31  1.3333333333333e-01
+6 31  3.3333333333334e-02
+13 31  1.1102230246252e-16
+14 31 -7.7715611723761e-16
+15 31  4.4408920985006e-16
+22 31 -3.3333333333334e-02
+23 31 -1.3333333333333e-01
+24 31 -3.3333333333334e-02
+31 31  0.0000000000000e+00
+4 32  1.1111111111111e-03
+5 32  4.4444444444444e-03
+6 32  1.1111111111111e-03
+13 32  4.4444444444446e-03
+14 32  1.7777777777778e-02
+15 32  4.4444444444444e-03
+22 32 -5.5555555555556e-03
+23 32 -2.2222222222222e-02
+24 32 -5.5555555555556e-03
+32 32  0.0000000000000e+00
+4 33  1.3333333333334e-02
+5 33  6.6666666666666e-02
+6 33  2.0000000000000e-02
+13 33  6.9388939039072e-17
+14 33 -1.6653345369377e-16
+22 33 -1.3333333333333e-02
+23 33 -6.6666666666667e-02
+24 33 -2.0000000000000e-02
+33 33  0.0000000000000e+00
+6 34  3.3333333333332e-02
+7 34  1.3333333333333e-01
+8 34  3.3333333333333e-02
+15 34 -4.7184478546569e-16
+17 34 -2.2204460492503e-16
+24 34 -3.3333333333331e-02
+34 34  0.0000000000000e+00
+40 34 -1.3333333333333e-01
+41 34 -3.3333333333334e-02
+6 35  1.1111111111110e-03
+7 35  4.4444444444444e-03
+8 35  1.1111111111112e-03
+15 35  4.4444444444444e-03
+16 35  1.7777777777777e-02
+17 35  4.4444444444441e-03
+24 35 -5.5555555555552e-03
+35 35  0.0000000000000e+00
+40 35 -2.2222222222222e-02
+41 35 -5.5555555555555e-03
+6 36  1.9999999999999e-02
+7 36  9.3333333333331e-02
+8 36  2.6666666666666e-02
+15 36 -3.1918911957973e-16
+16 36  3.8857805861880e-16
+17 36 -2.2204460492503e-16
+24 36 -1.9999999999999e-02
+36 36  0.0000000000000e+00
+40 36 -9.3333333333331e-02
+41 36 -2.6666666666667e-02
+8 37  3.3333333333334e-02
+9 37  1.3333333333333e-01
+17 37 -1.3877787807815e-16
+18 37 -6.6613381477509e-16
+37 37  0.0000000000000e+00
+41 37 -3.3333333333334e-02
+42 37 -1.3333333333333e-01
+8 38  1.1111111111111e-03
+9 38  4.4444444444443e-03
+17 38  4.4444444444448e-03
+18 38  1.7777777777778e-02
+38 38  0.0000000000000e+00
+41 38 -5.5555555555556e-03
+42 38 -2.2222222222222e-02
+8 39  2.6666666666667e-02
+9 39  1.2000000000000e-01
+17 39 -2.7755575615629e-16
+18 39 -3.3306690738755e-16
+39 39  0.0000000000000e+00
+41 39 -2.6666666666667e-02
+42 39 -1.2000000000000e-01
+6 40  1.1111111111111e-01
+7 40 -6.6613381477509e-15
+8 40  1.1111111111111e-01
+15 40 -3.5555555555555e-01
+16 40 -1.0666666666666e+00
+17 40 -3.5555555555553e-01
+24 40 -2.0000000000004e-01
+34 40 -1.3333333333333e-01
+35 40 -2.2222222222222e-02
+36 40 -9.3333333333331e-02
+40 40  1.9555555555555e+00
+41 40 -1.9999999999998e-01
+6 41 -2.2222222222222e-02
+7 41  1.1111111111112e-01
+8 41 -6.6666666666668e-02
+9 41  1.1111111111111e-01
+15 41  1.1111111111111e-01
+16 41 -3.5555555555558e-01
+17 41 -3.9999999999997e-01
+18 41 -3.5555555555555e-01
+24 41 -3.3333333333329e-02
+34 41 -3.3333333333334e-02
+35 41 -5.5555555555555e-03
+36 41 -2.6666666666667e-02
+37 41 -3.3333333333334e-02
+38 41 -5.5555555555556e-03
+39 41 -2.6666666666667e-02
+40 41 -1.9999999999998e-01
+41 41  1.2444444444445e+00
+42 41 -2.0000000000005e-01
+8 42  1.1111111111111e-01
+9 42  3.1086244689504e-15
+17 42 -3.5555555555551e-01
+18 42 -1.0666666666667e+00
+37 42 -1.3333333333333e-01
+38 42 -2.2222222222222e-02
+39 42 -1.2000000000000e-01
+41 42 -2.0000000000005e-01
+42 42  1.9555555555556e+00
diff --git a/data/fidapm05_rhs1.mtx b/data/fidapm05_rhs1.mtx
new file mode 100644
--- /dev/null
+++ b/data/fidapm05_rhs1.mtx
@@ -0,0 +1,44 @@
+%%MatrixMarket matrix array real general
+42 1
+ 2.6666666666667e-02
+ 1.3333333333334e-02
+ 2.6666666666667e-02
+ 1.3333333333333e-02
+ 2.6666666666667e-02
+ 1.3333333333333e-02
+ 2.6666666666666e-02
+ 1.3333333333334e-02
+ 2.6666666666667e-02
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
+ 0.0000000000000e+00
diff --git a/matrix-market-attoparsec.cabal b/matrix-market-attoparsec.cabal
new file mode 100644
--- /dev/null
+++ b/matrix-market-attoparsec.cabal
@@ -0,0 +1,61 @@
+name:                matrix-market-attoparsec
+version:             0.1.0.0
+synopsis:            Attoparsec parsers for the NIST Matrix Market format
+description:         Please see README.md
+homepage:            https://github.com/ocramz/matrix-market-attoparsec
+license:             BSD3
+license-file:        LICENSE
+author:              Marco Zocca
+maintainer:          zocca marco gmail
+copyright:           2017 Marco Zocca
+category:            Parsers
+build-type:          Simple
+extra-source-files:  README.md
+data-dir:            data
+data-files:          fidapm05.mtx
+                     fidapm05_rhs1.mtx                     
+cabal-version:       >=1.10
+tested-with:         GHC == 8.0.1
+
+
+                     
+library
+  default-language:    Haskell2010
+  ghc-options:         -Wall
+  hs-source-dirs:      src
+  exposed-modules:     Data.Matrix.MatrixMarket
+  other-modules:       Data.Matrix.MatrixMarket.Internal
+                       Control.Exception.Common
+  build-depends:       attoparsec  >= 0.10
+                     , base        >= 4.7 && < 5
+                     , bytestring  >= 0.9
+                     , directory
+                     , exceptions
+                     , scientific  >= 0.3.4.9
+                     , vector      >= 0.7
+
+-- executable matrix-market-attoparsec
+--   default-language:    Haskell2010
+--   ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+--   hs-source-dirs:      app
+--   main-is:             Main.hs
+--   build-depends:       base
+--                      , matrix-market-attoparsec
+
+test-suite spec
+  default-language:    Haskell2010
+  ghc-options:         -Wall
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  other-modules:       LibSpec
+  build-depends:       QuickCheck
+                     , base
+                     , exceptions
+                     , directory
+                     , hspec
+                     , matrix-market-attoparsec
+
+source-repository head
+  type:     git
+  location: https://github.com/ocramz/matrix-market-attoparsec
diff --git a/src/Control/Exception/Common.hs b/src/Control/Exception/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Exception/Common.hs
@@ -0,0 +1,11 @@
+module Control.Exception.Common where
+
+import Control.Exception
+import Control.Monad.Catch (MonadThrow (..))
+import Data.Typeable -- (TypeRep, Typeable, typeRep)
+
+
+data ImportError = FileParseError String String deriving (Eq, Typeable)
+instance Show ImportError where
+  show (FileParseError s s2) = unwords [s, ": File parse error:", s2]
+instance Exception ImportError
diff --git a/src/Data/Matrix/MatrixMarket.hs b/src/Data/Matrix/MatrixMarket.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Matrix/MatrixMarket.hs
@@ -0,0 +1,3 @@
+module Data.Matrix.MatrixMarket (module M) where
+
+import Data.Matrix.MatrixMarket.Internal as M
diff --git a/src/Data/Matrix/MatrixMarket/Internal.hs b/src/Data/Matrix/MatrixMarket/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Matrix/MatrixMarket/Internal.hs
@@ -0,0 +1,324 @@
+{-# LANGUAGE GADTs, OverloadedStrings, DeriveFunctor #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Matrix.MatrixMarket.Internal
+-- Copyright   :  (c) Marco Zocca 2017
+-- License     :  GPL-style (see the file LICENSE)
+--
+-- Maintainer  :  zocca marco gmail
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- Attoparsec parser and serializer for the NIST MatrixMarket format. The parser logic originally appeared in `accelerate-examples` and it is reused here (courtesy of T.McDonell and the `accelerate` developers) with some amendments.
+-- 
+-- In this version:
+-- *) Numbers are represented with Scientific notation instead of floating point
+-- *) Parsing rules are a bit relaxed to accommodate various whitespace corner cases
+--
+-----------------------------------------------------------------------------
+module Data.Matrix.MatrixMarket.Internal
+       (readMatrix, readArray,
+        writeMatrix, writeArray,
+        Matrix(..), Array(..),
+        Format (Coordinate, Array), Structure (General, Symmetric, Hermitian, Skew),
+        nnz, dim, numDat,
+        dimArr, numDatArr) where
+
+
+
+import Control.Applicative                      hiding ( many )
+
+import Data.Int
+import qualified Data.Char as C
+import Data.Complex
+import qualified Data.Scientific as S
+import Data.Attoparsec.ByteString.Char8 hiding (I)
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy.Char8 as B
+import qualified Data.Attoparsec.Lazy           as L
+import qualified Data.ByteString.Lazy           as L
+
+import Control.Monad.Catch
+import Control.Exception.Common
+
+
+
+-- | Specifies either sparse or dense storage.  In sparse (\"coordinate\")
+-- storage, elements are given in (i,j,x) triplets for matrices (or (i,x) for
+-- vectors).  Indices are 1-based, so that A(1,1) is the first element of a
+-- matrix, and x(1) is the first element of a vector.
+--
+-- In dense (\"array\") storage, elements are given in column-major order.
+--
+-- In both cases, each element is given on a separate line.
+--
+data Format = Coordinate | Array
+    deriving (Eq, Show)
+
+-- | Specifies the element type.  Pattern matrices do not have any elements,
+-- only indices, and only make sense for coordinate matrices and vectors.
+--
+data Field  = R | C | I | P
+    deriving (Eq, Show)
+             
+
+-- | Specifies any special structure in the matrix.  For symmetric and hermitian
+-- matrices, only the lower-triangular part of the matrix is given. For skew
+-- matrices, only the entries below the diagonal are stored.
+--
+data Structure = General | Symmetric | Hermitian | Skew
+    deriving (Eq, Show)
+
+
+-- | Sparse matrix in coordinate form (row, column, entry)
+-- NB: indices are 1-based i.e. A(1,1) is the top-left entry of matrix A
+data Matrix a = RMatrix (Int, Int) Int Structure [(Int, Int, a)]
+              | CMatrix (Int, Int) Int Structure [(Int, Int, Complex a)]
+              | PatternMatrix (Int,Int) Int  Structure [(Int32,Int32)]
+              | IntMatrix (Int,Int) Int Structure [(Int32,Int32,Int)]
+              deriving (Eq, Show)
+
+
+
+-- | Array, i.e. a DENSE matrix (also used to represent vectors as n-by-1 matrices)
+data Array a = RArray (Int, Int) Structure [a]
+             | CArray (Int, Int) Structure [Complex a]
+             deriving (Eq, Show)
+
+
+
+
+
+
+--------------------------------------------------------------------------------
+-- Attoparsec combinators
+--------------------------------------------------------------------------------
+
+comment :: Parser ()
+comment = char '%' *> skipWhile (not . eol) *> endOfLine
+  where
+    eol w = w `elem` ("\n\r" :: String)
+
+floating :: Parser S.Scientific
+floating = skipSpace' *> scientific
+
+integral :: Integral a => Parser a
+integral = skipSpace' *> decimal
+
+format :: Parser Format
+format =  string "coordinate" *> pure Coordinate
+      <|> string "array"      *> pure Array
+      <?> "matrix format"
+
+field :: Parser Field
+field =  string "real"    *> pure R
+     <|> string "complex" *> pure C
+     <|> string "integer" *> pure I
+     <|> string "pattern" *> pure P
+     <?> "matrix field"
+
+structure :: Parser Structure
+structure =  string "general"        *> pure General
+         <|> string "symmetric"      *> pure Symmetric
+         <|> string "hermitian"      *> pure Hermitian
+         <|> string "skew-symmetric" *> pure Skew
+         <?> "matrix structure"
+
+header :: Parser (Format,Field,Structure)
+header =  string "%%MatrixMarket matrix"
+       >> (,,) <$> (skipSpace' *> format)
+               <*> (skipSpace' *> field)
+               <*> (skipSpace' *> structure)
+               <*  endOfLine
+               <?> "MatrixMarket header"
+
+extentMatrix :: Parser (Int,Int,Int)
+extentMatrix = do
+  [m,n,l] <- skipSpace' *> count 3 integral <* endOfLine
+  return (m,n,l)
+
+extentArray :: Parser (Int,Int)
+extentArray = do
+  [m,n] <- skipSpace' *> count 2 integral <* endOfLine
+  return (m,n)
+
+line3 :: Integral i => Parser a -> Parser (i,i,a)
+line3 f = (,,) <$> integral
+               <*> integral
+               <*> f
+               <*  endOfLine
+
+skipSpace' :: Parser String
+skipSpace' = many' space
+
+
+--------------------------------------------------------------------------------
+-- Load and parse
+--------------------------------------------------------------------------------
+
+matrix :: Parser (Matrix S.Scientific)
+matrix = do
+  (f, t, s) <- header
+  (m, n, l) <- skipMany comment *> extentMatrix
+  if f /= Coordinate
+    then fail "matrix is not in Coordinate format"
+    else
+    case t of 
+     R -> RMatrix (m,n) l s <$> many1 (line3 floating)
+     C -> CMatrix (m,n) l s <$> many1 (line3 ((:+) <$> floating <*> floating))
+     I -> IntMatrix     (m,n) l s <$> many1 (line3 integral)
+     P -> PatternMatrix (m,n) l s <$> many1 ((,) <$> integral <*> integral)
+
+array :: Parser (Array S.Scientific)
+array = do
+  (f, t, s) <- header
+  (m, n) <- skipMany comment *> extentArray
+  if f /= Array
+    then fail "array is not in Array format"
+    else
+     case t of
+       R -> RArray (m,n) s <$> many1 floating
+       C -> CArray (m,n) s <$> many1 ((:+) <$> floating <*> floating)
+       _ -> fail "integer and pattern cases not relevant for the dense case"
+
+
+-- | Load a matrix (sparse, i.e. in Coordinate format) from file
+readMatrix :: FilePath -> IO (Matrix S.Scientific)
+readMatrix file = do
+  chunks <- L.readFile file
+  case L.parse matrix chunks of
+    L.Fail _ _ msg      -> throwM (FileParseError "readMatrix" msg)
+    L.Done _ mtx        -> return mtx
+
+-- | Load a dense matrix (i.e. a matrix or vector in Array format) from file
+readArray :: FilePath -> IO (Array S.Scientific)
+readArray file = do
+  chunks <- L.readFile file
+  case L.parse array chunks of
+    L.Fail _ _ msg      -> throwM (FileParseError "readArray" msg)
+    L.Done _ mtx        -> return mtx
+
+
+--------------------------------------------------------------------------------
+-- Write to file
+--------------------------------------------------------------------------------
+
+showFormat :: Format -> String
+showFormat = map C.toLower <$> show
+
+showField :: Field -> String
+showField f = case f of R -> "real"
+                        C -> "complex"
+                        I -> "integer"
+                        P -> "pattern"
+
+showStruct :: Structure -> String
+showStruct = map C.toLower <$> show
+
+-- %%MatrixMarket matrix coordinate real general
+
+headerStr :: Format -> Field -> Structure -> L.ByteString
+headerStr f t s =
+    B.pack $ unwords ["%%MatrixMarket matrix",
+                      showFormat f, showField t, showStruct s]
+
+
+nl :: L.ByteString
+nl = toLBS "\n" 
+
+showLines :: (a -> String) -> [a] -> L.ByteString
+showLines showf d = L.concat (L.pack . withNewline . showf <$> d) where
+  withNewline x = toEnum . C.ord <$> x ++ "\n"
+
+
+
+-- | Serialize a sparse matrix in Coordinate format
+writeMatrix :: Show b => FilePath -> Matrix b -> IO ()
+writeMatrix file mat = 
+  case mat of (RMatrix d nz s dat) -> 
+                L.writeFile file (matrixByteString d nz R s dat)
+              (CMatrix d nz s dat) -> 
+                L.writeFile file (matrixByteString d nz C s dat)
+              (IntMatrix d nz s dat) -> 
+                L.writeFile file (matrixByteString d nz I s dat)
+              _ -> error "writeMatrix : PatternMatrix not implemented yet"
+     where
+       matrixByteString di nz t s d =
+         L.concat [headerStr Coordinate t s,
+                   nl,
+                   headerSzMatrix di nz,
+                   nl,
+                   showLines sf3 d]
+         where
+         sf3 (i,j,x) = unwords [show i, show j, show x]
+         headerSzMatrix (m,n) numz = B.pack $ unwords [show m, show n, show numz] 
+
+-- | Serialize a dense matrix in Array format
+writeArray :: Show a => FilePath -> Array a -> IO ()  
+writeArray file arr = 
+  case arr of (RArray d s dat) -> L.writeFile file (arrayByteString d R s dat)
+              (CArray d s dat) -> L.writeFile file (arrayByteString d C s dat)
+    where
+      arrayByteString di t s d =
+        L.concat [headerStr Array t s,
+            nl,
+            headerSzArray di,
+            nl,
+            showLines show d] where
+        headerSzArray (m,n) = B.pack $ unwords [show m, show n]
+  
+  
+
+
+
+
+
+
+-- | helpers
+
+
+nnz :: Matrix t -> Int
+nnz m = case m of (RMatrix _ nz _ _) -> nz
+                  (CMatrix _ nz _ _) -> nz
+                  (PatternMatrix _ nz _ _) -> nz
+                  (IntMatrix _ nz _ _) -> nz
+
+dim :: Matrix t -> (Int, Int)
+dim m = case m of (RMatrix d _ _ _) -> d
+                  (CMatrix d _ _ _) -> d
+                  (PatternMatrix d _ _ _) -> d
+                  (IntMatrix d _ _ _) -> d
+
+numDat :: Matrix t -> Int
+numDat m = case m of (RMatrix _ _ _ d) -> length d
+                     (CMatrix _ _ _ d) -> length d
+                     (PatternMatrix _ _ _ d) -> length d
+                     (IntMatrix _ _ _ d) -> length d
+
+
+dimArr :: Array t -> (Int, Int)
+dimArr a = case a of (RArray d _ _) -> d
+                     (CArray d _ _) -> d
+ 
+numDatArr :: Array a -> Int
+numDatArr a = case a of (RArray _ _ ll) -> length ll 
+                        (CArray _ _ ll) -> length ll            
+
+
+
+
+-- | String -> ByteString
+-- NB: do not abuse
+toBS :: String -> BS.ByteString
+toBS x = BS.pack $ (toEnum . C.ord) <$> x
+
+-- | String -> lazy ByteString
+toLBS :: String -> L.ByteString
+toLBS x = L.pack $ (toEnum . C.ord) <$> x
+
+
+
+
+-- t1 = toBS "%%MatrixMarket matrix coordinate real general\n5  5  8\n1     1   1.000e+00\n2     2   1.050e+01\n3     3   1.500e-02\n1     4   6.000e+00\n4     2   2.505e+02\n4     4  -2.800e+02\n4     5   3.332e+01\n5     5   1.200e+01\n"
+
+-- t2 = toBS "%%MatrixMarket matrix coordinate real general\n5  5  8\n1     1   1.000e+00\n"
diff --git a/test/LibSpec.hs b/test/LibSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/LibSpec.hs
@@ -0,0 +1,69 @@
+module LibSpec where
+
+import Control.Exception
+import System.Directory (removeFile)
+
+import Test.Hspec
+import Test.Hspec.QuickCheck
+
+import Data.Matrix.MatrixMarket
+
+
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec =
+  describe "Data.Matrix.MatrixMarket" $ do
+    -- prop "ourAdd is commutative" $ \x y ->
+    --   ourAdd x y `shouldBe` ourAdd y x
+    it "fidapm05 : read/write/read roundtrip" $ do 
+      roundTrip Coordinate "fidapm05.mtx" -- fidapm05_rhs1.mtx
+    it "fidapm05_rhs1 : read/write/read roundtrip" $ do 
+      roundTrip Array "fidapm05_rhs1.mtx"
+    -- it "memplus : read/write/read roundtrip" $ do 
+    --   roundTrip "memplus.mtx"
+    -- it "memplus_rhs1 : imports all array entries" $ do 
+    --   x <- readArray "data/memplus_rhs1.mtx"
+    --   consistentDimsArr x `shouldBe` True    
+
+
+-- | Helpers
+
+-- | Check if matrix dimensions (read from header vs counted from memory) coincide
+-- NB : only valid for General matrices (in MatrixMarket, symmetric entries are not written on file)
+consistentDims :: Matrix t -> Bool
+consistentDims m = nnz m == numDat m
+
+-- check if array dimensions (read from header vs counted from memory) coincide
+consistentDimsArr :: Array a -> Bool
+consistentDimsArr mm = d == numDatArr mm where
+  (m,n) = dimArr mm
+  d = m*n
+
+
+dataDir = "data"
+
+roundTrip :: Format -> FilePath -> IO ()
+roundTrip f fname0 = do
+  let
+    fname = dataDir ++ "/" ++ fname0
+    ftemp = fname ++ "_temp"
+  if f == Coordinate
+    then do   
+    m0 <- readMatrix fname   -- load original
+    writeMatrix ftemp m0     -- save as temp
+    m1 <- readMatrix ftemp   -- load temp
+    m0 `shouldBe` m1
+    else do
+    m0 <- readArray fname   -- load original
+    writeArray ftemp m0     -- save as temp
+    m1 <- readArray ftemp   -- load temp
+    m0 `shouldBe` m1
+  removeFile ftemp         -- remove temp 
+
+
+-- withTempFile :: IO FilePath -> (FilePath -> IO c) -> IO c
+-- withTempFile createf = bracket createf removeFile
+
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
