我正在處理一些我們的教師給我們的Haskell函數示例。但我不明白這個特殊的功能:這段代碼如何產生這個輸出?
f x = [not a | a<-[x,not x], a]
和它產生[False]
作爲輸出,但我不明白爲什麼。請詳細解釋一下嗎?
我正在處理一些我們的教師給我們的Haskell函數示例。但我不明白這個特殊的功能:這段代碼如何產生這個輸出?
f x = [not a | a<-[x,not x], a]
和它產生[False]
作爲輸出,但我不明白爲什麼。請詳細解釋一下嗎?
這個列表解析出由三個部分組成:
[ not a | a <- [x, not x], a ]
-- ^yield^generator ^filter
的發生器從而讓a
迭代在具有兩個單元的明細表。那些元素是[True,False]
或[False,True]
(取決於值x
)。但是總是有相同的值(只有元素的順序不同)。
下一步過濾部分來自於a
。過濾器保留謂詞爲True
的值。這裏的謂詞只是a
:所以它保留了其中的配置a = True
。由於True
和False
爲a
列舉,這意味着我們將只考慮一個項目:其中a
是True
的項目。
這種價值,我們產生not a
。現在not True
當然是False
。因此,無論x
(只要它是True
或False
)的值,我們將始終生成[False]
。
這樣的結果:
Prelude> let f x = [not a | a<-[x,not x], a]
Prelude> f True
[False]
Prelude> f False
[False]
您也可以用等式推理明白這一點。先從列表理解:
f x = [not a | a <- [x, not x], a]
Desugar到列表單子:
f x = do
a <- [x, not x]
guard a
pure (not a)
Desugar do
符號:
f x = [x, not x] >>= \ a -> guard a >> return (not a)
內嵌的>>=
對列表的定義:
f x = concatMap (\ a -> guard a >> return (not a)) [x, not x]
內嵌guard
/>>
:
f x = concatMap (\ a -> if a then return (not a) else []) [x, not x]
內嵌return
:
f x = concatMap (\ a -> if a then [not a] else []) [x, not x]
展開concatMap g xs
到concat (map g xs)
:
f x = concat (map (\ a -> if a then [not a] else []) [x, not x])
內嵌map
:
f x = concat
[ if x then [not x] else []
, if not x then [not (not x)] else []
]
注意if x then [not x] else []
評估爲[False]
如果x
是True
和[]
如果x
是False
,那if not x then [not (not x)] else []
評估爲[]
如果x
是True
和[False]
如果x
是False
。因此,你必須:
f x = if x then [False] ++ [] else [] ++ [False]
而且,由於[False] ++ [] == [] ++ [False] == [False]
,您可以:
f x = [False]
謝謝!所以如果** yield部分是'a'而過濾器不是''結果會是'[TRUE]'**吧?另外爲什麼「一個過濾器只保留謂詞爲」True「的值?這是一條規則,因爲如果它剛剛出現在我腦海裏,那麼它可以是任何價值。你能解釋一下嗎?**過濾**部分請 – Snxby
@Snxby:不是,因爲如果過濾器不是'',那麼只允許'a = False',因此我們會產生'a',因此會再次導致'[False]'。 –
@Snxby你問爲什麼列表理解過濾器只保留謂詞給出'真'的值。這裏有兩個可能的答案,取決於你打算問什麼問題。如果你打算問「你怎麼知道這是行爲」,答案是[查看報告](https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-420003.11) 。如果你打算問「爲什麼選擇這種行爲」,答案是因爲只保留列表中的某些元素是一種常見的需求,而這是解決該需求的一種自然而簡單的方法。 –