LINUX.ORG.RU

История изменений

Исправление zinfandel, (текущая версия) :

многократного перечитывания конфига

Зачем, же. Читай конфиг один раз в начале, а потом передавай прочитанные значения в фунции.

Самым наивным подходом будет передавать каждое значение конфига как отдельный аргумент. Это быстро надоест и ты создашь ADT в котором будут сохранены все значения:

data Config = Config { redisConnection :: ConnectInfo
                     , ldapURI         :: String
                     , ldapUser        :: String
                     ...
                     }

И будешь явно передавать этот конфиг всем функциям.

Это тоже не лучший подход, потому что нужно явно передавать. Поэтому придумали монаду Reader, в которую можно засунуть этот конфиг и читать его из каждой функции. Но потом тебе нужно будет скомбинировать монаду Reader и монаду IO, для этого понадобяться монадные трансформеры. Почитай, http://habrahabr.ru/post/184722/ и Real World Haskell про монады и монадные трансформеры. Монадные трансформеры позволяют построить стек из монад, на котором обычно держится архитектура приложения. В твоем случае это будет выглядеть примерно вот так:

main :: IO ()
main = do
  conf <- readConfig
  runReaderT (ldapExecuteQuery m qwr) conf -- происходит вызов ldapExecuteQuery с неявной передачей конфига

data Config = Config { redisConnection :: ConnectInfo
                     , ldapURI         :: String
                     , ldapUser        :: String
                     ...
                     }

readConfig :: IO Config
readConfig = do
   connHost <- Con.load "connHost"
   let redisCon ConnectInfo {connectHost = connHost}
   ldapURI <- Con.load "ldapURI"
   ldapUser <- Con.load "ldapUser"
   return Config redisCon ldapURI ldapUser

type App = ReaderT Config IO

ldapExecuteQuery :: ByteString -> String -> App AnswerEmailCheck
ldapExecuteQuery m qwr = do
  conf{..} <- ask -- достаем конфиг
  conn <- ldapInitialize ldapURI -- конфиг передается неявно
  ldapSimpleBind conn -- конфиг передается неявно
  result <- ldapSearch conn ldapBDN LdapScopeSubtree (Just qwr) ldapAttrs False -- то же самое
  return $ getRes m result

ldapInitialize :: App Connection
ldapInitialize = undefined

ldapSimpleBind :: App Connection
ldapSimpleBind = undefined

ldapSearch :: App Connection
ldapSearch = undefined

Исправление zinfandel, :

многократного перечитывания конфига

Зачем, же. Читай конфиг один раз в начале, а потом передавай прочитанные значения в фунции.

Самым наивным подходом будет передавать каждое значение конфига как отдельный аргумент. Это быстро надоест и ты создашь ADT в котором будут сохранены все значения:

data Config = Config { redisConnection :: ConnectInfo
                     , ldapURI         :: String
                     , ldapUser        :: String
                     ...
                     }

И будешь явно передавать этот конфиг всем функциям.

Это тоже не лучший подход, потому что нужно явно передавать. Поэтому придумали монаду Reader, в которую можно засунуть этот конфиг и читать его из каждой функции. Но потом тебе нужно будет скомбинировать монаду Reader и монаду IO, для этого понадобяться монадные трансформеры. Почитай, http://habrahabr.ru/post/184722/ и Real World Haskell про монады и монадные трансформеры. Монадные трансформеры позволяют построить стек из монад, на котором обычно держится архитектура приложения. В твоем случае это будет выглядеть примерно вот так:

main :: IO ()
main = do
  conf <- readConfig
  runReaderT (ldapExecuteQuery m qwr) conf -- происходит вызов ldapExecuteQuery с неявной передачей конфига

data Config = Config { redisConnection :: ConnectInfo
                     , ldapURI         :: String
					 , ldapUser        :: String
                     ...
					 }

readConfig :: IO Config
readConfig = do
   connHost <- Con.load "connHost"
   let redisCon ConnectInfo {connectHost = connHost}
   ldapURI <- Con.load "ldapURI"
   ldapUser <- Con.load "ldapUser"
   return Config redisCon ldapURI ldapUser

type App = ReaderT Config IO

ldapExecuteQuery :: ByteString -> String -> App AnswerEmailCheck
ldapExecuteQuery m qwr = do
  conf{..} <- ask -- достаем конфиг
  conn <- ldapInitialize ldapURI -- конфиг передается неявно
  ldapSimpleBind conn -- конфиг передается неявно
  result <- ldapSearch conn ldapBDN LdapScopeSubtree (Just qwr) ldapAttrs False -- то же самое
  return $ getRes m result

ldapInitialize :: App Connection
ldapInitialize = undefined

ldapSimpleBind :: App Connection
ldapSimpleBind = undefined

ldapSearch :: App Connection
ldapSearch = undefined

Исходная версия zinfandel, :

многократного перечитывания конфига

Зачем, же. Читай конфиг один раз в начале, а потом передавай прочитанные значения в фунции.

Самым наивным подходом будет передавать каждое значение конфига как отдельный аргумент. Это быстро надоест и ты создашь ADT в котором будут сохранены все значения:

data Config = Config { redisConnection :: ConnectInfo
                     , ldapURI         :: String
	             , ldapUser        :: String
                     ...
		     }

И будешь явно передавать этот конфиг всем функциям.

Это тоже не лучший подход, потому что нужно явно передавать. Поэтому придумали монаду Reader, в которую можно засунуть этот конфиг и читать его из каждой функции. Но потом тебе нужно будет скомбинировать монаду Reader и монаду IO, для этого понадобяться монадные трансформеры. Почитай, http://habrahabr.ru/post/184722/ и Real World Haskell про монады и монадные трансформеры. Монадные трансформеры позволяют построить стек из монад, на котором обычно держится архитектура приложения. В твоем случае это будет выглядеть примерно вот так:

main :: IO ()
main = do
  conf <- readConfig
  runReaderT (ldapExecuteQuery m qwr) conf -- происходит вызов ldapExecuteQuery с неявной передачей конфига

data Config = Config { redisConnection :: ConnectInfo
                     , ldapURI         :: String
					 , ldapUser        :: String
                     ...
					 }

readConfig :: IO Config
readConfig = do
   connHost <- Con.load "connHost"
   let redisCon ConnectInfo {connectHost = connHost}
   ldapURI <- Con.load "ldapURI"
   ldapUser <- Con.load "ldapUser"
   return Config redisCon ldapURI ldapUser

type App = ReaderT Config IO

ldapExecuteQuery :: ByteString -> String -> App AnswerEmailCheck
ldapExecuteQuery m qwr = do
  conf{..} <- ask -- достаем конфиг
  conn <- ldapInitialize ldapURI -- конфиг передается неявно
  ldapSimpleBind conn -- конфиг передается неявно
  result <- ldapSearch conn ldapBDN LdapScopeSubtree (Just qwr) ldapAttrs False -- то же самое
  return $ getRes m result

ldapInitialize :: App Connection
ldapInitialize = undefined

ldapSimpleBind :: App Connection
ldapSimpleBind = undefined

ldapSearch :: App Connection
ldapSearch = undefined