Haskell 将以下约束默认为类型';双倍';使用科学
我有两个科学数字,它们必须是整数,我想转换成整数,如下所示 请忽略代码约定和代码的惯用性Haskell 将以下约束默认为类型';双倍';使用科学,haskell,Haskell,我有两个科学数字,它们必须是整数,我想转换成整数,如下所示 请忽略代码约定和代码的惯用性 > import qualified Data.Vector as V > import Data.Scientific > cToTy (Array v) = case V.toList v of > [String nm, Number p, Number s] > | all (==True) $ map isInteger [p,s] -- We
> import qualified Data.Vector as V
> import Data.Scientific
> cToTy (Array v) = case V.toList v of
> [String nm, Number p, Number s]
> | all (==True) $ map isInteger [p,s] -- We make sure they're always integers
> , [pr,sc] <- map (forceEitherToInt . floatingOrInteger) [p,s] -- And then hack them out
> forceEitherToInt :: (RealFloat r, Integral i) => Either r i -> Int
> forceEitherToInt (Left _a) = 0 -- This shouldn't happen, so we'll default it to 0 all the time.
> forceEitherToInt (Right a) = fromIntegral a
>导入限定数据。向量为V
>导入数据。科学
>cToTy(数组v)=案例v.toList v
>[字符串nm,编号p,编号s]
>| all(=True)$map是整数[p,s]——我们确保它们始终是整数
>,[pr,sc]强制点::(实浮点r,积分i)=>任一r i->Int
>forceeitherpoint(Left _a)=0——这不应该发生,因此我们将始终将其默认为0。
>强制点(右a)=来自积分a
然而,我得到这个警告,我不知道如何摆脱他们
JsonUtils.lhs:76:26: Warning:
Defaulting the following constraint(s) to type ‘Double’
(RealFloat r0) arising from a use of ‘forceEitherToInt’
In the first argument of ‘(.)’, namely ‘forceEitherToInt’
In the first argument of ‘map’, namely
‘(forceEitherToInt . floatingOrInteger)’
In a stmt of a pattern guard for
a case alternative:
[pr, sc] <- map (forceEitherToInt . floatingOrInteger) [p, s]
JsonUtils.lhs:76:26:警告:
将以下约束默认为类型“Double”
(RealFloat r0)因使用“ForceItherPoint”而产生
在“(.”的第一个参数中,即“forceeitherpoint”
在“map”的第一个参数中,即
“(forceeitherpoint.floatingornteger)”
在图案保护的stmt中
备选案例:
[pr,sc]首先,如果“两种情况都不应该发生”,您可以显式地导致错误;第二,您可以删除@bheklillr声明的RealFloat
;第三,如果您喜欢双精度,可以更具体地指定双精度;第四,如果你在名字中写“A from B”而不是“B to A”,那么它可以帮助你使用匈牙利符号。所以你可以写一个例子:
intFromEither :: (Integral i) => Either Double i -> Int
intFromEither (Left d) = error $
"intFromEither tried to coerce `Left " ++ show d ++ "` to an Int."
intFromEither (Right i) = fromIntegral i
您可以用x
替换上面的Double
,使其更通用;这里最常见的类型签名是(整数a,Num b)=>t a->b
首先,默认值(至少在本例中)是无害的p
和s
是多态的-类似于RealFloat a=>a
,但是ForceItherPoint
的返回类型不包括该类型,因此应用ForceItherPoint
时必须解除约束。为了使您的生活更简单,编译器会猜测使用哪种类型,而Double
并不是一个坏的选择。如果你真的想摆脱它,给应用程序或forceitherpoint
的定义一个单态类型签名。你是否需要forceitherpoint
来限制RealFloat
?如果您不使用它,您只需执行以下操作::(Integral i)=>r i->Int
我逐字地接受了您的解决方案,但仍然收到一条关于Integer的警告:将以下约束默认为键入“Integer”(Integral a0),这是由于在(.),即“map”的第一个参数中的“intfromore”,即“(intfromore.floatingornteger)”
@Arnon好的,因此,我认为缓解这一问题需要一些教学。Haskell具有用户可定义的模糊性;此功能称为“类型类”。然而,Haskell还允许您定义“默认”对于这些类型类(例如,“嘿,计算机,如果你不能解决歧义,就假设这个…”).RealFloat
默认值为Double
和Integral
默认值为Integer
。Haskell警告您,它是按原样做的,以防万一它不是您想要的。您可以指定Double Int->Int
使其选择显式,然后简化intfrom(右i)=我
。我可以发誓我已经试过了,它以前给过我警告-但现在它似乎起作用了。谢谢!