2017-03-08 71 views
-2

我已經通過了LYAH,但我覺得這不是一個很好的介紹給Haskell。我遇到了「對Haskell的一個溫和的介紹」,它推薦Richard Bird的「使用Haskell進行函數式編程入門」。這是我正在閱讀的書。第3章給出了一個數據類型Nat,並用它實現了基本的算術。從零開始實施自然數算術的難題

這是代碼我寫直到如今

module Main where 
import Prelude hiding ((^^)) 

data Nat = Zero | Succ Nat 
     deriving (Eq, Ord, Show) 
xx :: Nat -> Nat -> Nat 
m `xx` Zero = Zero 
m `xx` Succ n = (m `xx` n) `add` m 

(^^) :: Nat -> Nat -> Nat 
m ^^ Zero = Succ Zero 
m ^^ Succ n = (m ^^ n) `xx` m 

add :: Nat -> Nat -> Nat 
m `add` Zero = m 
m `add` Succ n = Succ(m `add` n) 

factsu :: Nat -> Nat 
factsu Zero  = Succ Zero 
factsu (Succ n) = Succ n `xx` factsu n 

--Zero = 0 

showNat :: Nat -> String 
showNat Zero = "Zero" 
showNat (Succ Zero) = "Succ Zero" 
showNat (Succ (Succ n)) = "Succ (" ++ showNat (Succ n) ++ ")" 

main :: IO() 
main = return() 

這是發生了什麼:

factsu Zero 
Succ Zero 
it :: Nat 

如何定義SUCC和零?

+2

你用*定義'Succ'和'Zero' *是什麼意思?你在文件中定義了它們... –

+0

@WillemVanOnsem我認爲它們被解釋爲字符串。 – learninghaskell

+2

不,你將它們定義爲:'數據Nat = Zero | Succ Nat'。因爲'Nat'是從'Show'派生的,所以你可以用'show(Succ Nat)'將它們轉換爲一個字符串。你也可以從'Read'派生出來,這樣你就可以將''Succ Zero''分析成'Succ Zero'。 –

回答

3

但我想零等於0

根本的問題是,你的意思是「我要Zero等於0」。一個字面的閱讀可能是「我想要Zero == (0 :: Integer)」,但這是不可能的,因爲Zero0 :: Integer有不同的類型 - 你的Zero真的是它自己的東西。沒有什麼可以阻止你,當然,從定義它們之間相互轉化的功能:

natToInteger :: Nat -> Integer 
integerToNat :: Integer -> Maybe Nat 

在另一方面,如果你只是想GHCI打印Zero爲「0」 ......

GHCi> Zero 
0 

。 ..所有你需要的是一個自定義Show實例,因爲karakfa和leftaroundabout建議in the comments。然而,這不會改變實際上的Zero;你只是改變它的顯示方式。

最後,第三個可能性是,你要使用數字文字的語法爲您Nat S:

GHCi> 0 + 2 :: Nat 
2 
it :: Nat 

如果你給一個Nat例如Num這實際上是可能的。不過,這可能是一個壞主意,因爲(-)將是部分的,並且negate(順便說一句,這也是爲什麼我在上面的integerToNat的簽名中加上了Maybe)沒有合理的實現。此外,就像Show的情況一樣,添加Num實例基本上不會改變您的Nat - 特別是在一天結束時,數字文字語法只是語法。

(你可能會質疑我的意思是「基本上」,如果你採取的認爲事情都是由你可以與他們做什麼特點的地步;但在此之前,我們太側鑽井我就講到這裏)

+0

我絕對是指第三種情況,我會嘗試實施。 – learninghaskell

+1

第三點讓我希望'Num'被拆分成一個具有'SemiRing'的層次結構。就像'class SemiGroup a where {zero :: a,(+):: a - > a - > a}',class SemiGroup a => Group a其中{negate :: a - > a,( - ): :a - > a - > a}','class SemiGroup a => SemiRing a where {one :: a,(*):: a - > a - > a}','class(SemiRing a,Group a) => Ring a where {fromInteger :: Integer - > a}',class ring a => IntegralDomain a where {div :: a - > a - > a}'。 – Alec

+2

@Alec當你想發現一個恰當的細粒度類層次結構是多麼痛苦時,總是有[數字前奏](https://hackage.haskell.org/package/numeric-prelude)。 –