[英]Haskell: Alternative to patterns of where f = foo e, e = bar d, d = baz c
[英]How to interpret fmap where f a = c -> d -> e
我正在嘗試理解一些代碼,並且使自己陷入困境。 請幫助我了解我的邏輯,或者缺乏邏輯...
開始:
*Main> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
如果我只是想讓fa
成為一個帶有一個參數的函數,那是可以的並且很有意義:
*Main> :t \f -> fmap f (undefined :: String -> Int)
\f -> fmap f (undefined :: String -> Int) :: (Int -> b) -> String -> b
我可以在第二個參數中傳遞一個String
,從而生成一個Int
,然后在第一個參數中使用該函數來生成b
。
現在,我希望fa
成為具有兩個參數的函數,因此我將其替換為:
*Main> :t \f -> fmap f (undefined :: String -> Int -> Bool)
\f -> fmap f (undefined :: String -> Int -> Bool)
:: ((Int -> Bool) -> b) -> String -> b
在這一點上,我很困惑。 我已經提供了將String
和Int
轉換為Bool
的函數。 現在如何提供另一個將 Int -> Bool
轉換為b
函數? 這是荒謬的還是我沒有讀正確的書?
還是這是函子中函子的一種情況,需要做更多工作才能使之有意義? 在這種情況下,該怎么辦?
在Haskell中,實際上不存在帶有兩個參數的函數。 每個函數只有一個參數。
特別地, String -> Int -> Bool
是一個接受一個String
參數的函數。 (當然,知道結果還是一個函數,就可以像使用帶有兩個參數的函數一樣使用它。)因此,如果要與fa
統一使用,則需要
f ~ (String->)
a ~ Int->Bool
實際上, Int->Bool
本身可以解釋為函子應用程序†
f ~ (String->)
g ~ (Int->)
b ~ Bool
這樣String->Int->Bool ~ f (gb)
; 從而
\f -> fmap (fmap f) (undefined :: String -> Int -> Bool)
:: (Bool -> b) -> String -> Int -> b
我認為函子的函數族並不是掌握函子/應用程序/單子的屬性的真正好例子。 列表和也許通常不太混亂; 當您需要該功能時(而不是雙關語),最好使用等效的Reader
而不是普通的函子。
關於您的原始表達,實際上並不是沒有意義的。 如果將其翻譯為更溫和的函子,我們可以例如編寫
> fmap ($2) [(>1), (>2), (>3)]
[True, False, False]
函數functor可以完成很多事情:
> fmap ($2) (<) 1
True
> fmap ($2) (<) 2
False
> fmap ($2) (<) 3
False
當然,該示例太簡單了,無法使用,但是您也可以實現非平凡的示例。
† 請注意, f
和g
實際上不是同一函子 。 我們傾向於看漲他們兩個“ 功能函子”,但真的是你得到一個不同的仿函數的每一個部分應用程序(->)
構造函數。 這意味着,即使存在Monad (a->)
實例,您也無法以任何方式統一這兩層。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.