2014-12-03 5 views
37

Für eine Monade M, Ist es möglich, A => M[B] in M[A => B] zu verwandeln?Drehen A => M [B] in M ​​[A => B]

Ich habe versucht, die Typen vergebens, was mich denken lässt, dass es nicht möglich ist, aber ich dachte, ich würde sowieso fragen. Auch die Suche nach Hoogle nach a -> m b -> m (a -> b) hat nichts zurückgegeben, also halte ich nicht viel Glück.

+6

(Randnotiz: Sie wollte wirklich 'Monad m => (a -> mb) -> m (a -> b)' von Hoogle Beachten Sie die zusätzlichen Klammern, Bedeutung. Ein Argument statt "zwei". Natürlich, wie Chi bewiesen hat, ist dieser Typ nicht bewohnt, abgesehen von der Verwendung von Bottom, so dass Sie immer noch keine Ergebnisse erhalten.) – AndrewC

Antwort

53

In der Praxis

Nein, es kann nicht, zumindest nicht in einer sinnvollen Art und Weise durchgeführt werden.

diesem Code Haskell Betrachten

action :: Int -> IO String 
action n = print n >> getLine 

Diese n erste nimmt, druckt er (IO hier ausgeführt), liest dann eine Linie vom Benutzer.

Angenommen, wir hatten eine hypothetische transform :: (a -> IO b) -> IO (a -> b). Dann als Gedankenexperiment betrachtet:

action' :: IO (Int -> String) 
action' = transform action 

Die oben hat alle IO im Voraus zu tun, bevor n zu wissen, und dann eine reine Funktion zurück. Dies kann nicht dem obigen Code entsprechen.

den Punkt betonen, betrachten diesen Unsinn Code unten:

test :: IO() 
test = do f <- action' 
      putStr "enter n" 
      n <- readLn 
      putStrLn (f n) 

Magisch, action' sollten im Voraus wissen, was der Benutzer neben geben wird! Eine Sitzung würde wie folgt aussehen:

Dies erfordert eine Zeitmaschine, so dass es nicht möglich ist.

In der Theorie

Nein, es kann nicht getan werden. Das Argument ähnelt the one I gave to a similar question.

Angenommen durch Widerspruch transform :: forall m a b. Monad m => (a -> m b) -> m (a -> b) existiert. Spezialisieren Sie m auf die Continuation Monad ((_ -> r) -> r) (Ich überlasse den newtype Wrapper).

transform :: forall a b r. (a -> (b -> r) -> r) -> ((a -> b) -> r) -> r 

Spezialisieren r=a:

transform :: forall a b. (a -> (b -> a) -> a) -> ((a -> b) -> a) -> a 

Bewerben:

transform const :: forall a b. ((a -> b) -> a) -> a 

Durch die Curry-Howard Isomorphismus ist folgendes ein intuitionistic Tautologie

((A -> B) -> A) -> A 

aber das ist Peirce " s Gesetz, das in intuitionistischer Logik nicht beweisbar ist. Widerspruch.

+0

Können Sie eine Definition für 'transform' geben? – ErikR

+4

@ user5402 'transform' ist eine theoretische Funktion, die von OP angefordert wurde – Odomontois

+4

@ user5402 Das obige zeigt tatsächlich, dass' transform' nicht implementiert werden kann. – chi

3

Nein

Zum Beispiel Option ist eine Monade, aber die Funktion (A => Option[B]) => Option[A => B] hat keine sinnvolle Umsetzung:

def transform[A, B](a: A => Option[B]): Option[A => B] = ??? 

Was Sie statt ??? platziere? Some? Some von was dann? Oder None?

+22

Obwohl die Antwort richtig ist, hüten Sie sich vor "Beweis durch mangelnde Vorstellungskraft". – luqui

4

Die anderen Antworten haben schön illustriert, dass es im Allgemeinen nicht möglich ist, eine Funktion von zu m (a -> b) für jede Monade m zu implementieren. Es gibt jedoch bestimmte Monaden, bei denen es durchaus möglich ist, diese Funktion zu implementieren. Ein Beispiel dafür ist der Leser Monade:

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