Ich bin auf ein Verhalten gestoßen, das ich in Haskell nicht erklären kann. Ich versuche, eine polymorphe Funktion in einem Datensatztyp zu speichern, den ich in einem ReaderT Monad verwenden möchte. Wenn ich meine Funktion mit asks
bekomme, erkennt der Compiler es nicht als polymorph und scheint den Typ beim ersten Auftreten der Funktion zu reparieren. Ich habe ein minimales Beispiel dafür in GHCI:Polymorphe Funktionen in Datensatztypen Haskell
{-# LANGUAGE Rank2Types #-}
data Test = Test {f :: (forall a. a -> a)}
runReaderT (asks f
>>= \f -> (liftIO . putStrLn $ show (f 2 :: Int))
>> (liftIO . putStrLn $ show (f "hello"))
) (Test id)
Beim Versuch, dies zu laufen, erhalte ich:
Couldn't match expected type ‘Int’ with actual type ‘[Char]’
In the first argument of ‘f’, namely ‘"hello"’
In the first argument of ‘show’, namely ‘(f "hello")’
In the second argument of ‘($)’, namely ‘show (f "hello")’
jedoch folgende Code funktioniert:
runReaderT (ask
>>= \(Test f) -> (liftIO . putStrLn $ show (f 2 :: Int))
>> (liftIO . putStrLn $ show (f "hello"))
) (Test id)
So ist es etwas, speziell mit asks
? Ich bin dankbar für jeden Hinweis darauf.
Ich denke, es zu tun hat mit 'f' nach dem \ erscheinen, wenn ich mich nicht irre, sind Lambda-Argumente, wenn Sie noch monomorphic anders angeben. – Ingo
Nur ein Kopf: Rank2Types ist eine veraltete Erweiterung, Aliasing RankNTypes. (Und RankNTypes erlaubt dir nur 'Forall's zu schreiben. Keine Rückmeldung vom Typ GHC, wie Ingo's Antwortdetails.) – hao