[英]Turning A => M[B] into M[A => B]
對於 monad M
,是否可以將A => M[B]
變成M[A => B]
?
我試過遵循這些類型無濟於事,這讓我認為這是不可能的,但我想我還是會問。 此外,在 Hoogle 中搜索a -> mb -> m (a -> b)
沒有返回任何內容,所以我沒有多少運氣。
不,它不能完成,至少不能以有意義的方式完成。
考慮這個 Haskell 代碼
action :: Int -> IO String
action n = print n >> getLine
這首先需要n
,打印它(在這里執行 IO),然后從用戶那里讀取一行。
假設我們有一個假設的transform :: (a -> IO b) -> IO (a -> b)
。 然后作為一個心理實驗,考慮:
action' :: IO (Int -> String)
action' = transform action
上面要提前做所有的IO,在知道n
之前,然后返回一個純函數。 這不能等同於上面的代碼。
為了強調這一點,請考慮下面的無意義代碼:
test :: IO ()
test = do f <- action'
putStr "enter n"
n <- readLn
putStrLn (f n)
神奇的是, action'
應該提前知道用戶接下來要輸入什么! 一個會話看起來像
42 (printed by action')
hello (typed by the user when getLine runs)
enter n
42 (typed by the user when readLn runs)
hello (printed by test)
這需要時間機器,所以無法做到。
不,這是不可能的。 這個論點類似於我對一個類似問題的論點。
假設通過矛盾transform :: forall ma b. Monad m => (a -> mb) -> m (a -> b)
transform :: forall ma b. Monad m => (a -> mb) -> m (a -> b)
存在。 將m
專門化為延續 monad ((_ -> r) -> r)
(我省略了 newtype 包裝器)。
transform :: forall a b r. (a -> (b -> r) -> r) -> ((a -> b) -> r) -> r
專門化r=a
:
transform :: forall a b. (a -> (b -> a) -> a) -> ((a -> b) -> a) -> a
申請:
transform const :: forall a b. ((a -> b) -> a) -> a
根據 Curry-Howard 同構,以下是一個直覺重言式
((A -> B) -> A) -> A
但這是皮爾斯定律,在直覺邏輯中無法證明。 矛盾。
其他回復很好地說明了一般來說,不可能為任何 monad m
實現從a -> mb
到m (a -> b)
的函數。 但是,在某些特定的 monad 中很可能實現此功能。 一個例子是 reader monad:
data Reader r a = R { unR :: r -> a }
commute :: (a -> Reader r b) -> Reader r (a -> b)
commute f = R $ \r a -> unR (f a) r
不。
例如, Option
是一個 monad,但是函數(A => Option[B]) => Option[A => B]
沒有有意義的實現:
def transform[A, B](a: A => Option[B]): Option[A => B] = ???
你用什么代替???
? Some
? Some
呢? 還是None
?
只是為了完成@svenningsson 的回答。 一個特別有用的例子是在 QuickCheck 中生成隨機函數。 那里的生成器定義為:
newtype Gen a = MkGen {
unGen :: QCGen -> Int -> a
}
它有一個Monad實例,它在某種意義上是Reader
但bind
總是為所有子計算拆分隨機生成器。
這意味着我們可以定義一個作用於生成器的函數作為函數的生成器!
promote :: (a -> Gen b) -> Gen (a -> b)
promote f = MkGen $ \gen n -> \a -> let MkGen h = f a in h gen n
而且在圖書館里更是普遍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.