我在 Haskell 中為我的大學作業撰寫了一個簡單的函式 - 該函式應該采用整數 n 并制作一個 ascii 三角形,底行為 2*n 1 寬。
這是我的實作:
module Triangle where
data TArg = CallArg Int | RecursiveArg (Int, Int)
triangle :: TArg -> String
triangle (CallArg k) = triangle (RecursiveArg (k, k))
triangle (RecursiveArg (0, _)) = ""
triangle (RecursiveArg (k, q)) = triangle (RecursiveArg (k-1, q 1)) spaces stars spaces ['\n'] where
spaces = replicate q ' '
stars = replicate (k*2 - 1) '*'
現在,雖然它有效 - 我不喜歡在呼叫函式時指定變體的必要性,并且寧愿使用某種強制或不同的方式來指定兩種可能的變體。
先感謝您
uj5u.com熱心網友回復:
看起來您正在嘗試使用呼叫包裝器設定遞回函式,因為遞回呼叫需要第二個引數。我認為您將引數封裝在資料結構中的方法不是一個好的方法。更常見的方法是創建兩個函式,一個是從定義外部呼叫的外部函式,一個是遞回呼叫的內部函式。通過使用范圍,您可以向外界隱藏遞回內部函式。為了實作這一點,我將重寫您的代碼如下
module Triangle where
triangle :: Int -> String
triangle k = triangle' k k where
triangle' :: Int -> Int -> String
triangle' 0 _ = ""
triangle' k q =
triangle' (k - 1) (q 1) spaces stars spaces "\n" where
spaces = replicate q ' '
stars = replicate (k * 2 - 1) '*'
uj5u.com熱心網友回復:
Andrew Ray 的回答是撰寫一個函式,該函式需要在其遞回形式中使用與在其初始呼叫中不同的呼叫簽名。
triangle但是為了補充這個答案,如果必須像 OP 中顯示的那樣存在,你會怎么做?1
如果您總是需要呼叫它并希望您可以呼叫它triangle (CallArg x),只需創建自己的包裝函式:xtriangle x
triangle' x = triangle (CallArg x)
-- or
triangle' = triangle . CallArg
現在,原始triangle檔案可以按照自己喜歡的方式進行簽名 ( TArg -> String),并且您可以使用您希望的簽名 ( Int -> String) 呼叫函式。每個人都贏了。并且包裝器是微不足道的,因此即使在純字符計數的基礎上,一旦您需要呼叫triangle'多次,使用包裝器的時間也會更短。
如果您希望避免呼叫不同名稱的非常??小的成本triangle,并且這是一個更現實的程式triangle,您可以從不同的模塊匯入一些東西,您可以定義自己的包裝器模塊:
module MyTriangle ( triangle )
where
import qualified Original.Triangle as OT
triangle = OT.triangle . OT.TArg
現在,您的其余代碼只需將匯入從import Original.Triangle ( triangle )to更改為import MyTriangle ( triangle ),并且您呼叫的所有(可能很多,如果這值得打擾)地方都triangle可以使用您喜歡的名稱和簽名。
概括地說:任何時候您想要多次使用的函式似乎具有比您實際需要的更復雜的簽名,因為它所采用的額外結構和/或值可以從您想要提供的內容中機械地派生出來,您可以簡單地創建一個進行翻譯的包裝器。你不需要語言來“隱式強制”任何東西;你可以明確地(但只能在一個地方)說出你希望它如何“強制”,給它一個名字,然后僅僅通過使用這個名字來獲得你想要的行為。這樣你就可以得到簡潔的代碼,避免冗余,并且所有發生的事情都是明確的。
(Andrew Ray 的回答中顯示的技術的核心實際上正是這種“翻譯包裝器”的想法,如果沒有外部人員需要呼叫包裝器之外的任何東西,也只是將原始函式移動為純粹的內部細節)
1說,因為它是您剛剛呼叫的第三方函式,和/或它有時實際上是在資料結構的情況下呼叫的,或者其他任何原因。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/506260.html
標籤:哈斯克尔
