【问题标题】:How to reuse IO-lifted function for different type?如何为不同类型重用 IO-lifted 功能?
【发布时间】:2014-09-17 13:14:31
【问题描述】:

以下代码

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"

我觉得很丑。

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

【问题讨论】:

    标签: haskell type-inference


    【解决方案1】:

    你被Dreaded monomorphism restriction咬了。最简单的解决方法是为您的函数添加类型签名:

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

    有关之前的一些 SO 讨论,请参阅 here

    【讨论】:

    • 或者保留代码原样并添加{-# LANGUAGE NoMonomorphismRestriction #-}
    • 有趣。非常感谢。
    猜你喜欢
    • 2013-12-30
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多