[英]Type defaults in `floor . sqrt`
使用-Wtype-defaults
(附帶-Wall
), floor . sqrt . fromIntegral
floor . sqrt . fromIntegral
即使我指定了參數的類型和結果, floor . sqrt . fromIntegral
給了我floor . sqrt . fromIntegral
警告:
λ> (floor . sqrt . fromIntegral) (10 :: Int) :: Int
<interactive>:356:2-6: warning: [-Wtype-defaults]
• Defaulting the following constraints to type ‘Double’
(RealFrac a0)
arising from a use of ‘floor’ at <interactive>:356:2-6
(Floating a0)
arising from a use of ‘sqrt’ at <interactive>:356:10-13
(Num a0)
arising from a use of ‘fromIntegral’ at <interactive>:356:17-28
• In the first argument of ‘(.)’, namely ‘floor’
In the expression: floor . sqrt . fromIntegral
In the expression: (floor . sqrt . fromIntegral) (10 :: Int) :: Int
<interactive>:356:2-6: warning: [-Wtype-defaults]
• Defaulting the following constraints to type ‘Double’
(RealFrac a0)
arising from a use of ‘floor’ at <interactive>:356:2-6
(Floating a0)
arising from a use of ‘sqrt’ at <interactive>:356:10-13
(Num a0)
arising from a use of ‘fromIntegral’ at <interactive>:356:17-28
• In the first argument of ‘(.)’, namely ‘floor’
In the expression: floor . sqrt . fromIntegral
In the expression: (floor . sqrt . fromIntegral) (10 :: Int) :: Int
3
通過為fromIntegral
指定非多態類型,我能夠解決這個問題:
λ> (floor . sqrt . (fromIntegral :: Int -> Double)) (10 :: Int) :: Int
3
以下也有效,但更加繁瑣:
λ> (floor . sqrt . (fromIntegral :: (Integral a) => a -> Double)) (10 :: Int) :: Int
3
我的問題是:
-Wtype-defaults
不符合條件。) fromIntegral
並且必須指定中間類型讓我想起了“簡單的事情很難”的諺語。 有三種類型可供選擇(輸入類型,內部使用的中間浮點類型和結果類型),您必須以某種方式告訴編譯器所有這三種類型。 有很多組合來固定它們,但你不能少於三個。
我認為TypeApplications
是一種指定這些類型的特別方便的方法。 這是從原始文件開始的一種方法,它有兩個注釋,只添加一個以避免默認:
> :set -XTypeApplications -Wtype-defaults
> (floor . sqrt @Double . fromIntegral) (10 :: Int) :: Int
3
這是另一個可能更符合人體工程學的因素(因為它更准確地說明了括號的位置):
> (floor . sqrt . fromIntegral @Int @Double) 10 :: Int
3
我喜歡你的第三個例子的想法,即修改你的第二個例子,這樣你就不必重復Int
,從而避免潛在的脆弱點。 通過使用特殊的_
應用程序,您可以使用類型應用程序以稍微不那么繁瑣的方式實現此目的,這使得編譯器可以使用其中一個類型變量的常用推理過程:
> (floor . sqrt . fromIntegral @_ @Double) (10 :: Int) :: Int
3
這是在Haskell中計算此復合函數(平方根的底面)的值的正確方法嗎? 必須使用
fromIntegral
並且必須指定中間類型讓我想起了“簡單的事情很難”的諺語。
您最終計算的是整數平方根,因此理想情況下,您希望避免通過sqrt :: Floating a => a -> a
來路由計算。 你可能會。 例如,使用integerSquareRoot :: Integral a => a -> a
從arithmoi庫。
至於你的第一個問題,我第二個Daniel Wagner建議使用TypeApplications
擴展來指定中間類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.