我正在嘗試在 Haskell 中使用泛型編程,并且需要對一組數字進行排序,但由于某種原因,當我運行代碼時,我收到一條錯誤訊息,指出“運算式中沒有 (Fractional Nums) 的實體:645.41 ....”每次看我的代碼,我都覺得有道理,但我不確定為什么它不起作用......
import Data.List (sortBy)
import Data.Ord (comparing)
data Nums = Nums {numbers::Double} deriving(Ord, Eq, Show)
sortNums :: [Nums] -> [Nums]
sortNums = sortBy(comparing numbers)
arr = [645.41, 37.59, 76.41, 5.31, 1.11, 1.10, 23.46, 635.47, 467.83, 62.25]
main:: IO ()
main =
do
print(sortNums arr)
如果這段代碼看起來很亂或沒有意義,我深表歉意,我是 Haskell 的新手......
uj5u.com熱心網友回復:
除非您有一個從問題中不明顯的充分理由,否則您可能應該Nums完全洗掉。
import Data.List (sort)
arr :: [Double]
arr = [645.41, 37.59, 76.41, 5.31, 1.11, 1.10, 23.46, 635.47, 467.83, 62.25]
main :: IO ()
main = print (sort arr)
uj5u.com熱心網友回復:
這里的問題是這arr是一個Doubles 的陣列,但你正在呼叫sortNums它,它需要一個Nums. 雖然這些實際上是“相同”的型別,但 Haskell 不會為您進行任何自動轉換。如果您替換print(sortNums arr)為print (sortNums (map Nums arr))- 以確保您正在排序的串列中的每個成員都有一個Nums值 - 那么這將按預期作業。
(不幸的是,您在此處收到的錯誤訊息相當令人困惑且無益,但源于這樣一個事實,即像字面量的浮點值645.41可以表示作為型別類實體的任何型別的值Fractional。GHC 看到您正在嘗試sortNums應用于串列,并且這需要一個 串列Nums,因此它會嘗試在型別串列中創建值Nums-它可以這樣做,但前提是存在Fractional實體,這就是您收到特定錯誤訊息的原因。別擔心太多關于這個 - 我只是想解釋為什么你會得到這個特定的錯誤,而不是像“無法將型別[Double]與預期型別匹配”這樣更有幫助的錯誤[Nums])
uj5u.com熱心網友回復:
要讓文字1或3.1415為您的型別作業,您需要它們分別是Num和的實體Fractional:
>> :type 1
1 :: Num p => p
>> :type 3.1415
3.1415 :: Fractional p => p
這意味著您可以將其實體1化為Intand Double,但不能將其實體化為您的Nums.
>> 1 :: Int
1
>> 1 :: Double
1.0
>> 1 :: Nums
<interactive>:36:1: error:
? No instance for (Num Nums) arising from the literal ‘1’
? In the expression: 1 :: Nums
In an equation for ‘it’: it = 1 :: Nums
類似地,您可以實體化3.1415asDouble但不是 as IntorNums因為沒有Fractional Int實體,也沒有Fractional Nums實體。
>> 1.0 :: Int
<interactive>:37:1-3: error:
? No instance for (Fractional Int) arising from the literal ‘1.0’
? In the expression: 1.0 :: Int
In an equation for ‘it’: it = 1.0 :: Int
>> 1.0 :: Double
1.0
>> 1.0 :: Nums
<interactive>:39:1-3: error:
? No instance for (Fractional Nums) arising from the literal ‘1.0’
? In the expression: 1.0 :: Nums
In an equation for ‘it’: it = 1.0 :: Nums
但是,可以Num為Fractional您的Nums.
- 使它成為一個
newtype而不是一個data型別。Double這使得它在運行時在表示上等于 a 。 - 這意味著您可以使用
GeneralizedNewtypeDeriving(newtype派生策略)來派生Num和Fractional為您的Nums型別(實際上是任何實體Double)。 - 您也可以使用
sortOn cmp=sortBy (comparing cmp)。
{-# Language DerivingStrategies #-}
{-# Language GeneralizedNewtypeDeriving #-}
{-# Language TypeApplications #-}
import Data.List (sortOn)
newtype Nums = Nums { numbers :: Double }
deriving
stock (Eq, Ord, Show)
deriving
newtype (Num, Fractional, Floating, Enum, Real, RealFloat, RealFrac)
sortNums :: [Nums] -> [Nums]
sortNums = sortOn numbers
arr :: Fractional a => [a]
arr = [645.41, 37.59, 76.41, 5.31, 1.11, 1.10, 23.46, 635.47, 467.83, 62.25]
-- >> main
-- [Nums {numbers = 1.1},Nums {numbers = 1.11},Nums {numbers = 5.31},Nums {numbers = 23.46},Nums {numbers = 37.59},Nums {numbers = 62.25},Nums {numbers = 76.41},Nums {numbers = 467.83},Nums {numbers = 635.47},Nums {numbers = 645.41}]
main :: IO ()
main = print (sortNums arr)
實際上,我們正在實體化arr :: [Nums]這僅是可能的,因為我們為 派生Fractional了新型別Nums:
>> :set -XTypeApplications
>>
>> arr @Float
[645.41,37.59,76.41,5.31,1.11,1.1,23.46,635.47,467.83,62.25]
>> arr @Double
[645.41,37.59,76.41,5.31,1.11,1.1,23.46,635.47,467.83,62.25]
>> arr @Double
[Nums {numbers = 645.41},Nums {numbers = 37.59},Nums {numbers = 76.41},Nums {numbers = 5.31},Nums {numbers = 1.11},Nums {numbers = 1.1},Nums {numbers = 23.46},Nums {numbers = 635.47},Nums {numbers = 467.83},Nums {numbers = 62.25}]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/532452.html
標籤:排序哈斯克尔仿制药
上一篇:如何在本機反應中過濾陣列?
下一篇:按列值對單行資料框進行排序
