簡體   English   中英

將 A => M[B] 變成 M[A => B]

[英]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 -> mbm (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實例,它在某種意義上是Readerbind總是為所有子計算拆分隨機生成器。

這意味着我們可以定義一個作用於生成器的函數作為函數的生成器!

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM