user2962064
user2962064

Reputation: 11

Graph transformation in Haskell

I am trying to understand how this codes transforms a file

contents <- readFile "graph.txt"
let graph = readGraph contents

readGraph = transpose . str2int . map words . lines
str2int = map.map $ zero2inf . fromIntegral . (\xs -> read xs :: Int)
zero2inf x = if x == 0 then 1/0 else x

the actual txt file has the following information

0  0  0  0  0
8  0  0  0  0
15 13 0  0  0
9  1  8  0  0
1  9  6  1  0

could someone give me a description of how the data looks like after the code is run is it a list? or what is it??

I think the important line here is

readGraph = transpose . str2int . map words . lines

Upvotes: 0

Views: 224

Answers (4)

user2962064
user2962064

Reputation: 11

I just wanted to know how the actual representation of the graph was and it is a list of lists... something like this

[[1/0,2,5],[2,1/0,6],[5,6,1/0]]

Upvotes: 0

J. Abrahamson
J. Abrahamson

Reputation: 74344

Here are the steps.

zero2inf :: (Num a, Eq a, Fractional a) => a -> a

(\xs -> read xs  :: Int) :: String -> Int
fromIntegral . <prev>    :: Num a => String -> a
zero2inf . <prev>        :: (Num a, Eq a, Fractional a) =>   String   ->   a
map <prev>               :: (Num a, Eq a, Fractional a) =>  [String]  ->  [a]
map <prev>               :: (Num a, Eq a, Fractional a) => [[String]] -> [[a]]
str2int = <prev>

lines                    :: String -> [String]
words                    :: String -> [String]
transpose                :: [[a]] -> [[a]]
map words                :: [String] -> [[String]]
map words . lines        :: String -> [[String]]
str2int . <prev>         :: ( Num a, Fractional a, Eq a )
                            => String -> [[a]]
transpose . <prev>       :: ( Num a, Fractional a, Eq a )
                            => String -> [[a]]

readFile                 :: String -> IO String
readFile "graph.txt"     :: IO String

do contents <- readFile "graph.txt"
   readGraph (contents :: String) :: ( Num a, Fractional a, Eq a ) => [[a]]

Upvotes: 4

aupiff
aupiff

Reputation: 1

Well, you can start by writing the code in a form that will run and be compiled by ghc, like this:

module Main where

import Data.List

readGraph = transpose . str2int . map words . lines

zero2inf x = if x == 0 then 1/0 else x

str2int = map.map $ zero2inf . fromIntegral . (\xs -> read xs :: Int)
main :: IO ()
main = do
    contents <- readFile "graph.txt"
    print $ readGraph contents

But besides that, use hoogle to look at what each individual function in readGraph does. lines breaks up a string into a list based on the location of newline chars, then words is mapped over the list to break each line of integers into separate integers based on the location of spaces, str2int transforms each string representing an integer to an actual integer type, and finally transpose (like a typical matrix transpose) exchanges all the rows and columns of the resultant integer matrix.

Upvotes: 0

Lee
Lee

Reputation: 144136

lines splits an input string on newline characters

words splits an input string on whitespace therefore map words is a function which converts a list of strings into a list of list of the words in each string

map words . lines therefore converts an input string into a list of list of strings. Given your input, this will be a matrix of strings in row-major order.

Your str2int function converts a list of list of strings and converts each element into an Int and then converts any zeros into 'infinity' (1/0).

str2int . map words . lines therefore reads the input matrix and converts all elements into a numeric type

Data.List.transpose transposes the rows and columns of its argument, so this just transposes the input matrix into column-major order.

readGraph therefore reads an input string containing a matrix in row-major order and converts it into a matrix of Doubles in column-major order.

Upvotes: 0

Related Questions