簡體   English   中英

在Haskell中使用自然數是否有實用的方法?

[英]Is there a practical way of using natural numbers in Haskell?

我正在學習Haskell,並希望在一些構造函數中強制使用正整數(1,2,3,...),但我似乎只能找到'Int'和'Integer'數據類型。

我可以使用規范

data Nat = Zero | Succ Nat

但后來我不能用1,4,......來表示它們。

所以我問,有沒有辦法實現這個目標? (就像在C中使用'unsigned')

提前致謝。

編輯:正如CA McCann所解釋的那樣,我將把它隱藏在一個模塊中。 另外,我必須添加以下鏈接: http//haskell.org/haskellwiki/Smart_constructors以獲取有關該主題的摘要。 感謝您抽出寶貴時間回答!

通常有兩種方法:您給出的歸納定義,或者使用其他東西進行內部表示的抽象數據類型。

請注意,歸納表示對於大數字而言並不是非常有效; 然而,它可以是懶惰的,這可以讓你做一些事情,比如看看兩個nat中哪一個更大,而不進一步評估較小的那個。

抽象數據類型是在單獨的模塊中定義的並且不導出其構造函數的類型,例如IOData.Set.Set 你可以定義這樣的東西:

module Nat (Nat() {- etc. -} ) where

newtype Nat = Nat { unNat :: Integer }

...在Nat上導出各種操作,即使內部表示只是Integer ,也要確保沒有構造Nat類型的值保持負值。

在這兩種情況下,如果你想使用數字文字,你需要一個fromInteger的定義,它被附加到Num類型類,這對於自然數是完全錯誤的但是很好。

如果你不介意制作一個破壞的實例只是為了獲得語法細節,你可以這樣做:

instance Num Nat where
    Zero + n = n
    n + Zero = n
    (Succ n1) + (Succ n2) = Succ . Succ $ n1 + n2

    fromInteger 0 = Zero
    fromInteger i | i > 0 = Succ . fromInteger $ i - 1

......等等,用於其他功能。 對於抽象數據類型方法也可以這樣做,只是注意不要使用deriving來獲取自動Num實例 ,因為它會愉快地打破你的非負約束。

您可以使用Data.Word中的Word32 ,它對應於C中的uint32_t。

使用Word32,您會遇到與C中的無符號類型相同的問題,尤其是上溢和下溢。 如果要確保不會發生這種情況,則需要將其包裝為newtype並僅導出智能構造函數。 因此,不可能有加法,減法等,並且不存在上溢或下溢的風險。 例如,如果要支持添加,可以添加和導出用於添加無符號整數的函數,但檢查溢出(並且會降低性能)。 它可能看起來像這樣:

module NT(UInt, addUInts) where

import Data.Word

newtype UInt = UInt Word32
  deriving (Show)

mkUInt :: Word32 -> UInt
mkUInt = UInt

addUInts :: UInt -> UInt -> Maybe UInt
addUInts (UInt u1) (UInt u2) =
  let u64 :: Word64
      u64 = fromIntegral u1 + fromIntegral u2
  in if u64 > fromIntegral (maxBound :: Word32)
       then Nothing
       else Just (UInt (fromIntegral u64))

我不記得它是否解決了你的具體問題,但你可能會喜歡Colin Runciman的論文。自然數字怎么樣? 如果你無法克服付費牆, Citeseer似乎有一個版本

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM