考虑这个例子:
applyKTimes :: Integral i => i -> (a -> a) -> a -> a
applyKTimes 0 _ x = x
applyKTimes k f x = applyKTimes (k-1) f (f x)
applyThrice :: (a -> a) -> a -> a
applyThrice = applyKTimes 3
Run Code Online (Sandbox Code Playgroud)
该3在applyThrice通过GHC默认为一个Integer与编译时如图所示-Wall:
Warning: Defaulting the following constraint(s) to type 'Integer'
'Integral t'
arising from a use of 'applyKTimes'
Run Code Online (Sandbox Code Playgroud)
所以我猜这Integer是默认的Integral a => a.
-Wall …最近我一直在玩Haskell,特别是整个仿函数概念.我越深入其中,我得到的时刻越多,它肯定会让我的多巴胺受体相当多.
我坚持的问题如下.这是有效的代码,它提升了函数,然后首先将其应用于IO值,然后应用于List.
replicator1 =
fmap (replicate 3)
replicator2 =
fmap (replicate 3)
main = do
replicated <- replicator1 getLine
print (replicator2 replicated)
Run Code Online (Sandbox Code Playgroud)
以更简洁的方式编写它是非常诱人的,即:
replicator =
fmap (replicate 3)
main = do
replicated <- replicator getLine
print (replicator replicated)
Run Code Online (Sandbox Code Playgroud)
我的一部分说它在概念上是正确的,因为replicator它既可以应用于IO也可以应用于List实例,但是作为强类型语言Haskell不允许我这样做.我想我非常明白为什么会这样.
问题是:有什么方法可以让我更接近后一种变体?或者和前者住在一起好吗?
谢谢!
我一直在玩uncurryGHCi 的功能,我发现了一些我根本无法得到的东西.当我申请uncurry的(+)功能,并结合该像在下面的代码中的一些变量,所述编译器推断它的类型是特定于Integer:
Prelude> let add = uncurry (+)
Prelude> :t add
add :: (Integer, Integer) -> Integer
Run Code Online (Sandbox Code Playgroud)
但是,当询问以下表达式的类型时,我得到(我期望的)正确的结果:
Prelude> :t uncurry (+)
uncurry (+) :: (Num a) => (a, a) -> a
Run Code Online (Sandbox Code Playgroud)
会导致什么?这是GHCi特有的吗?
这同样适用于let add' = (+).
注意:我无法使用编译文件重现它.
鉴于这行代码(我在这个答案中首次看到):
pVal :: Num a => a
pVal = sum . map fromIntegral $ ([1..10000000] :: [Int])
Run Code Online (Sandbox Code Playgroud)
如果它被用作多种类型,那么表达式是否为每种类型完全重新评估?每种类型都有一个结果吗?
例如:
pInt :: Int
pInt = pVal
pDub :: Double
pDub = pVal
Run Code Online (Sandbox Code Playgroud) 我在理解为什么推断类型签名与我期望的不同时遇到了一些困难.让我们举个例子(我试着让它尽可能短):
import Control.Applicative
import Data.Word
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Token
import Text.Parsec.Language (emptyDef)
import Text.Parsec.Prim
import Data.Functor.Identity
--parseUInt' :: Num b => ParsecT String u Identity b
parseUInt' = fromInteger <$> decimal (makeTokenParser emptyDef)
--parseUInt1 = fromInteger <$> decimal (makeTokenParser emptyDef)
--parseUInt2 = fromInteger <$> decimal (makeTokenParser emptyDef)
parsePairOfInts = do
x <- parseUInt'
char ','
y <- parseUInt'
return $ (x, y)
parseLine :: String -> Either ParseError (Word32, Word8)
parseLine = parse parsePairOfInts "(error)"
main = print . show …Run Code Online (Sandbox Code Playgroud) 我通过从ghci检查它来声明类型声明但是加载模块会给出错误:
even-fibbanaci-sum.hs:7:12: error:
Couldn't match expected type ‘a’ with actual type ‘Double’
‘a’ is a rigid type variable bound by
the type signature for:
getFib :: forall b a. (Integral b, Floating a) => b -> a
at even-fibbanaci-sum.hs:4:12
In the expression: ((phi ^ n) - (minusphi ^ n)) / sqrt 5
In an equation for ‘getFib’:
getFib n = ((phi ^ n) - (minusphi ^ n)) / sqrt 5 • Relevant bindings include
getFib :: b -> a (bound …Run Code Online (Sandbox Code Playgroud) 以下代码
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' …Run Code Online (Sandbox Code Playgroud)