2013-07-03 43 views
1
data Point = Point Float Float deriving (Show) 
data Line = Line Point Point deriving (Show)  
onLine :: Line -> Point -> Bool 
onLine (Line (Point x1 y1) (Point x2 y2)) (Point x y) = True 

有沒有辦法不使用這麼多的括號?Haskell代碼中是否需要括號

+0

你可以刪除'Show'獲得子句周圍括號。你無能爲力;畢竟,你如何將對手模式彼此分開而不用花括號? –

回答

5

我推薦一個名爲hlint的工具來識別可以簡化代碼的地方。

在您的代碼/書面/,你不使用的值x1y1x2y2xy,所以你可以這樣寫:

onLine _ _ = True 

不過,我認爲這只是一個存根,實際上你會用變量做一些事情。一般來說,如果您確實需要引用所有這些變量,那麼您需要按照您所做的方式編寫它。但是,也許你正在使用一個只需要整行值的幫助函數。然後,你可以寫這樣的:

onLine l p = blah blah blah 
    -- use slope l and yIntercept l to figure out if p is on the line 

slope :: Line -> Float 
slope (Line (Point x1 y1) (Point x2 y2)) = (y2 - y1)/(x2 - x1) 

yIntercept :: Line -> Float 
yIntercept (Line (Point x1 y1) (Point x2 y2)) = blah blah blah 

或者,你可以只使用訪問函數來提取點和線的X和Y座標,但在這種情況下,它可能使你的代碼混亂。

另外,在Haskell中,我認爲使用Double而不是Float通常更有效。

+0

謝謝你最後的提示!我還發現,通過使用浮動我不能使用負數,如-1。有什麼建議麼 ? – osager

+4

您可以使用負數,只是有時您需要將它們括在圓括號中。請參閱真實世界Haskell第1章中的「算術怪癖:寫負數」(http://book.realworldhaskell.org/read/getting-started.html) – mhwombat

1

您可以通過定義訪問器來取消函數中的直線和點,但是如果沒有括號,則無法進行模式匹配。

3

有時可以使用記錄符號避免使用括號,有時使用$,有時使用中綴函數,有時如果不是過多,也可以。

讓我們使用記錄表示法獲得座標的大量訪問權限,但我們將僅保留Line

data Point = Point {x::Double,y::Double} deriving (Show) 
data Line = Line Point Point deriving (Show)  

這定義了x :: Point -> Doubley :: Point -> Double

有作爲浮點平等沒有這樣的事情,但我還是要大致右:

accuracy = 0.000000000001 

is :: Double -> Double -> Bool 
is x y = abs (x - y) < accuracy 

我可以用這個作爲x point1 `is` x point2整齊地避免了括號is (x point1) (x point2)

當你的數據結構沒有如此嚴重地與模式匹配嵌套,幾個括號易於閱讀:

gradient :: Line -> Double 
gradient (Line one two) = (y two - y one)/(x two - x one) 

但是,我們可以去一個更深的機智由於功能xy,使用過多的方括號。

asFunction :: Line -> (Double -> Double) -- () for clarity, not necessity 
asFunction [email protected](Line point _) = \xx -> gradient l * (xx - x point) + y point 

通知我用[email protected]引入一個別名(Line point _)節省打字的權利。

現在我們可以使用中綴函數招擺脫幾個括號:

onLine :: Line -> Point -> Bool 
onLine l p = l `asFunction` x p `is` y p 

在右手邊,你可以使用$來擺脫括號,但你不能使用它在模式匹配的左邊,因爲它是一個函數f $ x = f x。例如

this (that (the other thing (something other))) 
= this $ that $ the other thing $ something other 
= this . that . the other thing $ something other 
+0

謝謝@leftaroundabout。這確實是我的意圖。 – AndrewC

1

擺脫括號的另一種方式是做模式匹配在一些情況下的表達式:

onLine l p = case l of 
    Line p1 p2 -> case p1 of 
     Point x1 y1 -> case p2 of 
      Point x2 y2 -> case p of 
       Point x y -> True -- you can use x1,y1,x2,y2,x and y here 

這是緊挨什麼編譯器「翻譯」的patternmatches到,但這當然不是一個很大的改進!

但是,有很多寫這個表達式的方法,也是轉換爲相同的級聯模式匹配;這裏有一個:

onLine l p = let 
    Line (Point x1 y1) (Point x2 y2) = l 
    Point x y = p 
    in True 

和這裏的另一個:

onLine l p = True where 
    Line (Point x1 y1) (Point x2 y2) = l 
    Point x y = p 

最後一個是相當不錯的,可讀性,在我看來,但其他建議要好得多,因爲他們會帶來更好的結構化程序!

(有關於我粉飾無可辯駁的模式,單構造數據類型這僅適用於一些東西)