2014-09-17 4 views
1

Следующий кодКак повторно использовать функцию IO-lifted для разных типов?

import Control.Applicative 
import Control.Arrow 
import Data.List.Split 

main :: IO() 
main = do 
    ints <- getNumberLine 
    integers <- getNumberLine 
    print $ foo ints integers 

getNumberLine = readDataLine <$> getLine 

readDataLine :: Read a => String -> [a] 
readDataLine = splitOn " " >>> map read 

foo :: [Int] -> [Integer] -> String 
foo _ _ = "hello" 

дает сообщение об ошибке:

GetNumberLine.hs:9:22: 
    Couldn't match type `Int' with `Integer' 
    Expected type: [Integer] 
     Actual type: [Int] 
    In the second argument of `foo', namely `integers' 
    In the second argument of `($)', namely `foo ints integers' 
    In a stmt of a 'do' block: print $ foo ints integers 
Failed, modules loaded: none. 

Он работает только тогда, когда я создаю вторую функцию getNumberLine:

import Control.Applicative 
import Control.Arrow 
import Data.List.Split 

main :: IO() 
main = do 
    ints <- getNumberLine 
    integers <- getNumberLine2 
    print $ foo ints integers 

getNumberLine = readDataLine <$> getLine 
getNumberLine2 = readDataLine <$> getLine 

readDataLine :: Read a => String -> [a] 
readDataLine = splitOn " " >>> map read 

foo :: [Int] -> [Integer] -> String 
foo _ _ = "hello" 

который я нахожу довольно некрасиво.

Зачем это необходимо? И есть ли лучший способ?

ответ

5

Вы были укушены Dreaded monomorphism restriction. Самое простое исправление для добавления сигнатуры типа вашей функции:

getNumberLine :: Read a => IO [a] 
getNumberLine = readDataLine <$> getLine 

См here для некоторого предыдущего обсуждения SO.

+2

Или оставьте код как есть и добавьте '{- # LANGUAGE NoMonomorphismRestriction # -}' –

+0

Интересно. Большое спасибо. –

Смежные вопросы