2014-10-28 67 views
2

我有兩個科學數字,它們是我想要轉換爲Ints的整數,如下所示。默認情況下,使用Scientific時輸入'Double'的限制

請忽略代碼慣例和代碼的慣用性。

> 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 

但是,我得到這個警告,我不知道如何擺脫他們。

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] 

有沒有人有任何想法或想法?

+1

首先,違約(至少在這種情況下)是無害的。 'p'和's'是多態的 - 類似於'RealFloat a => a',但是'forceEitherToInt'的返回類型不包含該類型,所以當'forceEitherToInt'應用時約束必須放棄。爲了讓你的生活更簡單,編譯器會猜測使用哪種類型 - 而「Double」並不是一個錯誤的選擇。如果你真的想擺脫它,給應用程序*或* forceEitherToInt定義一個單形式簽名。 – user2407038 2014-10-28 16:14:56

+1

你需要'forceEitherToInt'來限制'RealFloat'嗎?你沒有使用它,你可以'forceEitherToInt ::(Integral i)=> ri - > Int' – bheklilr 2014-10-28 16:15:22

回答

3

首先,如果「不應該發生」,您可以明確地導致錯誤;第二,你可以放棄RealFloat作爲@bheklilr狀態;第三你可以更具體地指定雙倍,如果你更喜歡雙倍;第四,如果你在名字中寫'A從B'而不是'B到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 

,可隨時更換Double以上x,使之更加普遍;這裏最常用的簽名是(Integral a, Num b) => Either t a -> b

+0

我逐字提出了你的解決方案,我仍然得到一個警告,這次是關於Integer的:'默認下面的約束(')'的第一個參數,即'intFromEither' 在'map'的第一個參數中,即 '(int) (intFromEither。floatingOrInteger)'' – Arnon 2014-10-29 08:12:27

+1

@Arnon好吧,所以我認爲減輕這個需要一點教學。 Haskell具有用戶可定義的含糊性;這個功能被稱爲「類型類」。然而,Haskell還允許你爲這些類型類定義「默認」(即「如果你不能解決歧義只是假設這是......」,嘿,計算機)。 'RealFloat'默認爲'Double','Integral'默認爲'Integer'。 Haskell警告你它正在這樣做,以防萬一它不是你想要的。你可以指定'Either Double Int - > Int'來明確它的選擇,然後簡化'intFromEither(Right i)= i'。 – 2014-10-29 19:02:33

+0

我可以發誓我已經嘗試過,它給了我警告之前 - 但它似乎現在工作。謝謝! – Arnon 2014-10-30 07:28:16