Home > Software design >  Is it possible to return a nested list as IO()
Is it possible to return a nested list as IO()

Time:10-26

I have some simple functions and I need makeMove to return IO():

toPole :: Show a => [a] -> [a] -> String
toPole fpole spole = show(head fpole:spole)

fromPole :: Show a => [a] -> String
fromPole fpole = show (tail fpole)

makeMove :: [a] -> [a] -> IO ()
makeMove [] _ = return ()
makeMove fpole spole = putStr (unwords p)
     where p = [fromPole fpole, toPole fpole spole]

The idea is that I have two lists, and I want to move the first item of the list fpole to the second list spole, and print them as a nested list [[],[]] with putStr. Is there a way to achieve this? I've tried different things with the return type of toPole and fromPole, but figured it was easier to convert makeMove to IO() if the return type was String.

The error I get arises from fromPole fpole in where p = [fromPole fpole, ...:

No instance for (Show a) arising from a use of ‘fromPole’

CodePudding user response:

makeMove also needs the Show a constraint. As it stands, you are saying that makeMove can accept lists of any type as arguments, but then you try to pass those possibly Show-less values to fromPole.

makeMove :: Show a => [a] -> [a] -> IO ()
makeMove [] _ = return ()
makeMove fpole spole = putStr (unwords p)
     where p = [fromPole fpole, toPole fpole spole]

A cleaner implementation wouldn't have either toPole or fromPole making any assumptions about the list elements; in fact, they are barely necessary. You can define makeMove (arguably more clearly) without them.

transfer :: [a] -> [a] -> ([a], [a])
transfer (x:xs) ys = (xs, (x:ys))

makeMove :: Show a => [a] -> [a] -> String
makeMove fpole spole = let (fpole', spole') = transfer fpole spole
                       in unwords [fpole', spole']

showMove :: Show a => [a] -> [a] -> IO ()
showMove fpole spole = print (makeMove fpole spole)

Here, I've decomposed the function into three logical parts:

  1. transfer simply moves an element from one pole to the other.
  2. makeMove creates a String from the result of transfer
  3. showMove outputs the result of the move.

As much work as possible is kept in pure functions, with only showMove having any dependency on IO.

  • Related