Last active
January 6, 2020 08:12
-
-
Save drchaos/3e5834472fee96f2331f33a16f1cae53 to your computer and use it in GitHub Desktop.
Maybe examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include | |
#include | |
#include | |
#include | |
#include | |
#include | |
#include | |
/* fmap definitions */ | |
struct fmap_base | |
{ | |
struct none_value {}; | |
template <typename just_t> | |
struct just | |
{ | |
just_t m_just; | |
template<typename... params_t> | |
just(params_t&&... pp) : m_just{ std::forward<params_t>(pp)... } {} | |
template<typename unused_param_t> | |
const just_t& operator()(unused_param_t&&) const { return m_just; } | |
}; | |
template <> | |
struct just<none_value> | |
{ | |
template<typename... params_t> | |
just(params_t&&... pp) {} | |
none_value operator()() const { return none_value{}; } | |
}; | |
template <typename res_t, typename intermediate_res_t> | |
struct fmap_failed | |
{ | |
fmap_failed(res_t& ret, intermediate_res_t&&) | |
{ | |
ret = res_t{}; | |
} | |
}; | |
}; | |
template | |
struct fmap : public fmap_base | |
{ | |
private: | |
template <typename intermediate_res_t, typename fn_t, typename... functors> | |
struct fmap_ | |
{ | |
fmap_(res_t& ret, intermediate_res_t&& r, fn_t&& fn, functors&&... ff) | |
{ | |
if (auto r1 = fn(std::forward<intermediate_res_t>(r))) | |
{ | |
fmap_<decltype(r1), functors...>(ret, std::move(r1), std::forward<functors>(ff)...); | |
} | |
else | |
{ | |
fmap_failed<res_t, decltype(r1)>( ret, std::move(r1)); | |
}; | |
} | |
}; | |
template <typename intermediate_res_t, typename fn_t> | |
struct fmap_<intermediate_res_t, fn_t> | |
{ | |
fmap_(res_t& ret, intermediate_res_t&& r, fn_t&& fn) | |
{ | |
ret = fn(std::forward<intermediate_res_t>(r)); | |
} | |
}; | |
public: | |
template <typename... functors> | |
fmap(res_t& ret, functors&&...ff) { | |
fmap_{ ret, | |
none_value{}, | |
std::forward<functors>(ff)... }; | |
} | |
}; | |
/* usage definitions, | |
I use separate types for each stage just for illutrative purposes | |
*/ | |
struct search_pattern : public std::string | |
{ | |
using std::string::string; | |
operator bool() const { return !empty(); } | |
}; | |
struct found_param : std::optionalstd::size_t | |
{ | |
using std::optionalstd::size_t::optional; | |
// no need to define operator bool() as we borrow it from optional | |
}; | |
struct found_value : std::optionalstd::string | |
{ | |
using std::optionalstd::string::optional; | |
// no need to define operator bool() as we borrow it from optional | |
}; | |
struct param_list { | |
std::array<std::pair<const char*, const char*>, 1> m_storage{ std::make_pair("good_pattern", "value") }; | |
}; | |
found_param find_param(const search_pattern& p, const param_list& params) | |
{ | |
return params.m_storage[0].first == p ? found_param{ 0 } : found_param{}; | |
} | |
found_value find_env_var(const found_param& v, const param_list& params) | |
{ | |
// we do not attempt to validate if v contains valid index to illustrate it would never be called if p was not found before | |
return found_value{ params.m_storage[*v].second }; | |
} | |
int main() | |
{ | |
param_list params{}; | |
found_value good_res{}, bad_res{}; | |
fmap<found_value>{ good_res, // <- contains "value" at exit | |
fmap<found_value>::just<search_pattern>("good_pattern") | |
, [¶ms](const search_pattern& p) -> auto { return find_param(p, params); } | |
, [¶ms](const found_param& p) -> auto { return find_env_var(p, params); } | |
}; | |
fmap<found_value>{ bad_res, // <- contains nothing at exit | |
fmap<found_value>::just<search_pattern>("bad_pattern") | |
,[¶ms](const search_pattern& p) -> auto { return find_param(p, params); } | |
,[¶ms](const found_param& p) -> auto { return find_env_var(p, params); } | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Вариант с последовательным поиском | |
lookupParam :: String -> [(String,String)] -> Maybe String | |
-- реализация | |
lookupEnvVar :: String -> [(String,String)] -> Maybe String | |
-- реализация | |
seqLookup :: String -> [(String,String)] -> [(String,String)] -> Maybe String | |
seqLookup paramName params envVars = do | |
envVarName <- lookupParam paramName params | |
value <- lookupEnvVar envVarName envVars | |
return value | |
-- Вариант с альтернативным поиском | |
altLookup :: String -> [(String,String)] -> [(String,String)] -> Maybe String | |
altLookup paramName = lookupParam paramName params <|> envVarName paramName params | |
-- или | |
altLookup' :: String -> [(String,String)] -> [(String,String)] -> Maybe String | |
altLookup' paramName = asum [ lookupParam paramName params | |
, envVarName paramName params | |
] | |
-- тут `asum` это просто свёртка списка с помощью `<|>` | |
-- `foldr (<|>) empty l`, где empty - это Nothing для нашего случая, а l - и есть наш список | |
-- этот вариант интереснее тем, что явно виден порядок альтернатив поиска и этот список проще расширять | |
-- Другая интересная штука, что благодаря ленивости если первый поиск удачен, то второй не будет вызван никогда |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
`#include
#include
#include
#include
#include
#include
#include
/* fmap definitions */
struct fmap_base
{
struct none_value {};
};
template
struct fmap : public fmap_base
{
private:
public:
};
/* usage definitions,
I use separate types for each stage just for illutrative purposes
*/
struct search_pattern : public std::string
{
using std::string::string;
};
struct found_param : std::optionalstd::size_t
{
using std::optionalstd::size_t::optional;
};
struct found_value : std::optionalstd::string
{
using std::optionalstd::string::optional;
};
struct param_list {
std::array<std::pair<const char*, const char*>, 1> m_storage{ std::make_pair("good_pattern", "value") };
};
found_param find_param(const search_pattern& p, const param_list& params)
{
return params.m_storage[0].first == p ? found_param{ 0 } : found_param{};
}
found_value find_env_var(const found_param& v, const param_list& params)
{
// we do not attempt to validate if v contains valid index to illustrate it would never be called if p was not found before
return found_value{ params.m_storage[*v].second };
}
int main()
{
param_list params{};
}
`