IO isolation is not a defect, but a feature of Haskell, and one of its clear success.
If you want to serialize data to file, and load data back into your program, you don't have to do that by hand. Use any serializing library, there are many of them. You can also use the great Aeson library, that can convert your data in JSON and load them back.
If you want to do that by hand for any reason, you must first define your own file format, and have it unambiguous. For example, what happens on your example if name contains a space ?
Then you should define a function that can parse one line of your file format and produce a Participant readParticipant :: String -> Maybe Participant. Notice the maybe, because if the string is ill-formated, your function won't be able to create a participant out of its hat, so it will produce a Nothing.
Then you can have a function that parse a list of participants (notice the plural) readParticipants :: String -> [Participants]. No Maybe here because the list itself allows for failure.
Now you can have a tiny IO function that will read the file content, and run readParticipants on it.
readParticipantsIO :: IO [Participants]
readParticipantsIO = readParticipants <$> readFile "participants.data"
-- alternative definition, exact same behaviour in this case
readParticipantsIO :: IO [Participants]
readParticipantsIO = do
content <- readFile "participants.data"
return $ readParticipants content
IO String.