2016-07-23 12 views
1

In Python haben wir ein eingebautes Paket namens "operator", mit dem wir die Funktionsversion eines beliebigen Operators verwenden können. Es wird in hohem Maße verwendet, wenn "funktionale Programmierung" -Funktionen wie Map und Reduce verwendet werden, und ist viel besser zu empfehlen als die Verwendung von "Lambda".Was ist die "::" äquivalente Funktion in Haskell?

Ich habe das gleiche Problem in Haskell: I t Benutzer MAPM irgendwo mit einer Zusammensetzung von vielen Funktionen wünschen, aber ich habe nicht so recht Lambda zu verwenden:

mapM ((\x->x::String).fromSql.(!!1)) res 

Gibt es eine gleichwertige zu diesem liek dies:

mapM (someFunc(String).fromSql.(!!1)) res 
+4

Es ist möglich, "id @String" in GHC 8.0 zu tun: https://ghc.haskell.org/trac/ghc/wiki/TypeApplication –

+0

'mapM (asTypeOf" ".fromSql. (!! 1)) res "- es sei denn, Sie haben" XOverloadedStrings "aktiviert. – Michael

+1

Sind Sie sicher, dass 'mapM (fromSql. (!! 1)) res' nicht ausreicht, oder' mapM ((fromSql. (!! 1)) :: a -> String) res'? – chepner

Antwort

1

::String ist kein Operator im Sinne der Pythons string(…), aber eine Typanmerkung, und als solche besonderen syntaktischen Regeln gelten.

Sie können jedoch definieren Funktion

asString :: String -> String 
asString x = x 

und dann schreiben

mapM (asString.fromSql.(!!1)) res 

@augustss einmal proposed a language extension die (::String) verwendet werden erlauben würde, aber ich kann es jetzt nicht finden.)

+1

!! 1 bedeutet nicht Kopf, da es das zweite Element nicht das erste erhält. Ich meine nicht die Identität, ich möchte nur einen Typ Hinweis zu mehrdeutigen Typ Fehler zu stoppen. – Kamyar

+0

Ja, ich habe den Punkt: Wenn wir eine Identity-Funktion mit konkreten Typ haben, können wir es wie einen Typhinweis verwenden. Aber gibt es einen anderen Weg, als es wieder zu definieren? – Kamyar

+0

Das scheint viel zu viel Arbeit zu sein, um einfach eine Typannotation zu geben. Der Typ des Ausdrucks mapM ...res 'kann selbst angegeben werden, und von dieser Art Inferenz wird wahrscheinlich der richtige Typ für 'fromSql' gefunden. Alternativ kann man 'fromSQL :: _ -> String' schreiben (mit -XPartialTypeSignatures) – user2407038

1

Als Chepner kommentierte, sollte es wirklich nicht notwendig sein, irgendeinen Typhinweis überhaupt zu geben: alles, was Sie brauchen, ist

mapM (fromSql . (!!1)) res 

... das heißt, sofern Sie tatsächlich das Ergebnis in irgendeiner Weise verwenden. (Wenn Sie das Ergebnis nicht verwenden, warum tun Sie das überhaupt?)

Der Grund dafür ist: Im Gegensatz zu Python hat Haskell ein richtiges Hindley-Milner-Typ-System, und dies kann Typen in jedem schließen Richtung und jeden Kontext. Also, wenn Sie nur schreiben, zum Beispiel,

do 
    sqlStrs <- mapM (fromSql . (!!1)) res 
    ... 
    mapM_ putStrLn sqlStr 

dann ist dies genug für den Compiler, dass sqlStrs :: [String] zu schließen und damit fromSql muss eingeschränkt werden String zu ergeben.


Es gibt einige Ausnahmen, aber diese entstehen nur mit der Monomorphismus Einschränkung (die globalen Definitionen gilt nur, nicht auf etwas in einer Monade gebunden, und auch ausgeschaltet werden kann) oder bei der Verwendung von Erweiterungen wie GADTs, ExistentialQuantification oder RankNTypes.

Verwandte Themen