星期日, 7月 27, 2008

Haskell Learning Note(2)

欠稿很大,預估要寫到folder後才能停一下。

環境
建議是用ghc(The Glasgow Haskell Compiler),大部分的環境都有提供binary,直接安裝即可,而ghci是一個互動介面,較為常用指令如下。

  • :q 離開ghci
  • :l xd.hs 載入某個module(Haskell副檔名為.hs)
  • :r 重新載入module
  • :e 編輯所載入的module的文字檔(我在mac上,預設是用vim開啟)

簡單的開始
如果撰寫了一個function,可以使用:t 來看其形別要求,舉個例子

Prelude> :t sum . map read . words
sum . map read . words :: (Read a, Num a) => String -> a
剛開始學習,學會看type是一件非常重要的事。然而,就此打住,想先講講一些別的東西

Just Function
在Haskell中最小的組成單位是function,想要表達一堆資料,可以用list(不知道對不對,不過倒是知道list沒有這麼簡單),一個function必有其input 和 output,然而,我學習的第一個問題,怎麼樣得知input和output的要求為何,如果跟C++ STL一樣,use type as an argument,必有其限制,所以:t非常的重要(因為就是拿來看型別要求),在Haskell裡,有著非常神奇的type system,有好幾次我問Josh,為什麼會如此時,卻超出我的範圍,以剛剛說的例子而言

Prelude> :t words
words :: String -> [String]
(yen3註:一個String為input,產生一個為String的List)

Prelude> :t read
read :: (Read a) => String -> a
(yen3註: 一個String為input,產生一個型別為a符合Read的要求)

Prelude> :t map
map :: (a -> b) -> [a] -> [b]
(yen3註: map是一個神奇的function,基本原理就是,input為一個list,output也是一個list,但是map會套用一個function,將list of a轉換到list of b,簡單的來說,就是對每個元素做同一個動作)

Prelude> :t sum
sum :: (Num a) => [a] -> a
(yen3註: input 為一個list,輸出後型別為a符合Num的要求)
接著再回來看看原來的例子
Prelude> :t sum . map read . words
sum . map read . words :: (Read a, Num a) => String -> a
(yen3註: 變的很明顯,輸入一個字串,而輸出一個型別為a符合 Read 和 Num,全部串起來做一次就會變成...)

Prelude> sum . map read . words $ "123 456"
579
(yen3註:把字串根據空白分開成為個一list,然後每個元素被讀取成某一個型別之後,sum把每個元素做一求和的動作。)
其實這一行沒有解釋的很清楚,何謂Read要求 ? 還有,轉型的時候為什麼要轉成a? 這就再說XD (因為我也不會XD) 其實就學到這裡的時候,可以猜到一件事,Haskell自己幫你做了非常多的事,很多事硬要推測到底,其實反正看不懂。看清楚一個function的要求為何,似乎變的很重要,看懂他的運作方式會更有趣



每次連載都不會寫太長,基本上都是利用專題空閒寫作,我就盡量寫啦XD


---
基本上這篇的註都是大膽的猜測,但是想不到要用什麼字XD

1 則留言:

T55555 提到...

>其實這一行沒有解釋的很清楚,何謂Read要求 ? 還有,轉型的時候為什麼要轉成a? 這就再說XD (因為我也不會XD)

You need to know more about type class.
"Read" is a type class (which defined function(s) that instance must to have).

For example, you can only use == when both side are "Eq" instance.
:t (==)
(==) :: (Eq a) => a -> a -> Bool
Here a is a type parameter and (Eq a) means the type "a" must be an instance of Eq.

Now, read :: (Read a) => String -> a
means read function will only return a value of type "a" that must be instance of "Read".
(Because Read class defined the parse string function to allow read to call and get the value )

The post was on 2008, I believed that, now 2010, you should already know these things. ;-)