如何重用不同类型的IO提升功能?

Tob*_*ann 1 haskell type-inference

以下代码

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"
Run Code Online (Sandbox Code Playgroud)

给出此错误消息:

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.
Run Code Online (Sandbox Code Playgroud)

它只有在我创建第二个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"
Run Code Online (Sandbox Code Playgroud)

我觉得很难看.

为什么这有必要?还有更好的方法吗?

Ørj*_*sen 5

你被可怕的单态限制困扰.最简单的解决方法是为函数添加类型签名:

getNumberLine :: Read a => IO [a]
getNumberLine = readDataLine <$> getLine
Run Code Online (Sandbox Code Playgroud)

这里对于一些以前的SO讨论.

  • 或者按原样保留代码并添加`{ - #LANGUAGE NoMonomorphismRestriction# - }` (2认同)