2016-07-23 5 views
1

В Python у нас есть встроенный пакет с именем «operator», с помощью которого мы можем использовать функциональную версию любого оператора. Он широко используется при использовании функций «функционального программирования», таких как карта и уменьшение, и рекомендуется гораздо лучше, чем при использовании «лямбда».Что такое эквивалентная функция «::» в Haskell?

У меня такая же проблема в Haskell: Я хочу, чтобы т пользователя mapM где-то с композицией многих функций, но я должен использовать не так довольно лямбда:

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

Есть ли эквивалент этой Лик это:

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

В «GHC 8.0» можно сделать «id @String»: https://ghc.haskell.org/trac/ghc/wiki/TypeApplication –

+0

'mapM (asTypeOf" ".fromSql. (!! 1)) res' - если у вас нет 'XOverloadedStrings'. – Michael

+1

Вы уверены, что 'mapM (fromSql. (!! 1)) res' недостаточно, или 'mapM ((fromSql. (!! 1)) :: a -> String) res'? – chepner

ответ

1

::String не является оператором в смысле питона string(…), но тип аннотации, а также такие специальные синтаксические правила.

Вы можете, однако, определить функции

asString :: String -> String 
asString x = x 

, а затем написать

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

@augustss раз proposed a language extension, что позволило бы (::String) быть использованы, но я не могу найти его прямо сейчас.)

+1

!! 1 не означает голову, так как он получает второй элемент не первый. Я не имею в виду идентификатор, я просто хочу, чтобы подсказка типа перестала получать неоднозначную ошибку типа. – Kamyar

+0

Да, я понял: если у нас есть функция идентификации с конкретным типом, мы можем использовать ее как подсказку типа. Но есть ли другой способ, кроме определения его снова? – Kamyar

+0

Это похоже на слишком много работы, чтобы просто дать аннотацию типа .. тип выражения 'mapM ...res' может сам быть указан, и из этого типа вывод скорее всего найдет правильный тип для 'fromSql'. В качестве альтернативы можно написать 'fromSQL :: _ -> String' (с -XPartialTypeSignatures) – user2407038

1

Как комментировал chepner, на самом деле нет необходимости давать какие-либо намеки на тип: все, что вам нужно, - это

mapM (fromSql . (!!1)) res 

... то есть, если вы действительно используете результат каким-то образом. (Если вы не используете результат, то почему вы это делаете в первую очередь?)

Причина: в отличие от Python, Haskell имеет правильную систему типа Hindley-Milner, и это может вызывать типы в любом направление и в любом контексте. Так что если вы пишете только, например,

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

то это достаточно для того, чтобы компилятор сделать вывод, что sqlStrs :: [String] и, следовательно, fromSql должно быть ограничено, чтобы получить String.


Есть некоторые исключения, но они возникают только с ограничением мономорфизма (который относится только к глобальным определениям, а не к чему-то, связанному в монаде, а также может быть выключен) или при использовании расширения, такие как GADT, ExistentialQuantification или RankNTypes.

Смежные вопросы