我是 Haskell 函式式編程的新手。我從多個來源學習了 lambda 函式、串列、型別、記錄語法和仿函式,例如Learn You a Haskell for Great Good 一書,名為Get Programming With Haskell。我對函式的作業原理和函式式編程的要點有了一些了解。在這一點上,我停留在需要在 lamda 函式中使用記錄串列的地方,這是 map 函式的引數。
在這里我分享可運行的代碼。
我有一個人的記錄
data Person = Person
{name :: Name
,lastname :: LastName
,personId :: Int
,sex :: Int
,parentList :: [Int]
,childList :: [Int]
,siblingList :: [Int]
}
deriving (Show,Typeable,Data,Eq)
1-我有一個getParentListPerson :: Person-> [Person] -> [Person] 函式,它使用 [Person] 串列回傳給定 Person 的父母。(我在每個人中都抱著每個人::[Person])
getParentListPerson :: Person-> [Person] -> [Person]
getParentListPerson p ps = filter((\px -> elem (personId p) (childList px))) ps
2-如果第一個引數和第二個引數是cousens,則回傳true的isCousen函式。(其中第一人稱的父母應該在第二人稱的父母的兄弟名單中)
isCousen :: Person -> Person -> Bool
isCousen p1 p2 =any f (parentList p1)
where f= (\x -> elem x $ map func2 $ func3 p2 everybody):([Int]->Bool)
func2 = (\y -> (siblingList y))::(Person->[Int])
func3 = (\z k-> getParentListPerson z k)::(Person->[Person]->[Person])
在這里,我要做的是創建一個lambda 函式 f ,它接受 parentList ([Int]) 并找到任何匹配的人。
- f :: [整數]->布爾
- funcs2 :: Person -> [Int]。
- func3 :: Person -> [Person] -> [Person]。
當我運行這個時,我得到了這個錯誤:( 據我所知,雖然我想在 where 子句中使用map將Person給 func2 ,但我無法實作。我知道 map 需要一個函式和一個串列。所以我假設func3 不能回傳[Person]。所以問題應該出在 getParentListPerson 函式中)
app\Main.hs:89:24: error:
* Couldn't match type `Int' with `[Int]'
Expected type: [[Int]]
Actual type: [Int]
* In the second argument of `any', namely `(parentList p1)'
In the expression: any f (parentList p1)
In an equation for `isCousen':
isCousen p1 p2
= any f (parentList p1)
where
f = (\ x -> elem x <$> concatMap func2 <$> func3 p2 everybody) ::
([Int] -> Bool)
func2 = (\ y -> (siblingList y)) :: (Person -> [Int])
func3
= (\ z k -> getParentListPerson z k) ::
(Person -> [Person] -> [Person])
|
89 | isCousen p1 p2 =any f (parentList p1)
| ^^^^^^^^^^^^^
它說我給出了 [Int],其中預期的引數應該是 [[Int]]。我有點失落。任何幫助,將不勝感激。我懷疑我可能會錯誤地使用map函式和lambda 函式,但我已盡我所能。據我所知,它們似乎是正確的
uj5u.com熱心網友回復:
問題是func2回傳一個串列,這意味著map func2回傳一個串列串列。您可能想要做的是將這些連接在一起。從而改變:
elem x $ map func2 $ func3 p2 everybody
進入:
elem x $ concat $ map func2 $ func3 p2 everybody
還有一個和的組合,concat即map你concatMap可以將其簡化為:
elem x $ concatMap func2 $ func3 p2 everybody
根據 chi 的評論,您似乎已經切換到這個,這反映在錯誤訊息中,盡管您仍然保持原始代碼不變。這樣做的問題似乎是您還替換$了each<$>不正確<$>的,因為與map. 如果你想使用<$>你可以map像這樣替換它:
elem x $ concat $ func2 <$> func3 p2 everybody
然后我還可以注意到您的某些功能可以如何簡化(即使您沒有問過這個問題)。您不需要使用所有或任何這些簡化,但您至少可以考慮它們。
在以下函式中,您使用 lambda。
func2 = (\y -> (siblingList y))
func3 = (\z k-> getParentListPerson z k)
由于 lambda 是整個運算式,因此您可以對這些運算式使用普通函式語法而不是 lambda,如下所示:
func2 y = siblingList y
func3 z k = getParentListPerson z k
但是現在您還可以注意到,它們除了將引數應用于函式之外什么都不做,因此它們等效于:
func2 = siblingList
func3 = getParentListPerson
但是因為現在我們可以看到func2并且func3基本上只是函式別名,我們可以洗掉它們并在定義中替換siblingList它們getParentListPerson,f如下所示:
f = (\x -> elem x $ concatMap siblingList $ getParentListPerson p2 everybody)
在這里,您還可以洗掉 lambda:
f x = elem x $ concatMap siblingList $ getParentListPerson p2 everybody
你也可以getParentListPerson用類似的方式稍微簡化一下。或者,您也可以改為使用,parentList盡管您需要將每個轉換Int為Person.
順便說一句,函式名稱中的“表親”一詞拼寫錯誤isCousen。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/487899.html
