Giter VIP home page Giter VIP logo

neither's People

Contributors

dvdfreitag avatar ingve avatar nikhedonia avatar njlr avatar rvarago avatar wojciechmigda avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

neither's Issues

Handling polymorphic errors and values

Does this library support polymorphism on the left-hand-side or the right-hand-side of the Either type? Looking at the code right now, it doesn't look like it because the value will be moved into the supertype. If this is true, I would like to propose this as a feature.

It would probably require some bit-fiddling and storing the data as a raw buffer, but I'm quite certain it can work.

Implement MetaFunctions ensureEither

To express the type contracts of (left/right) flatMap and map, we should introduce meta functions for SFINAE.

template<class L, class R>
auto ensureEither( Either<L,R> const& e) - > decltype( e ) {
   return e;
}

template<class L, class R>
auto ensureEither( Either<L,R> const& e, L, R ) - > decltype( e ) {
   return e;
}

template<class L, class R>
auto ensureEitherLeft( Either<L,R> const& e, L) - > decltype( e ) {
   return e;
}

template<class L, class R>
auto ensureEitherRight( Either<L,R> const& e, R) - > decltype( e ) {
   return e;
}

This could be used to express the contracts of map:

  template<class LeftCase>
  auto leftFlatMap(LeftCase leftCase) -> decltype(
    ensureEitherRight( leftCase(leftValue), rightValue ) 
  ) {
    if (!*this) {
      return leftCase( leftValue );
    }

    return NextEither::rightOf(rightValue);
}

Uniform initialization causes problems with gcc

Uniform initialization (curly braces initialization) is being used in either.hpp, and while there should be nothing wrong with that some compilers do not handle this well.

For instance, uniform initialization causes problems with nlohmann's json library compiled with gcc, as backed with this issue: nlohmann/json#985

So, using neither with gcc and json objects causes the latter being modified.

As an excercise I have removed uniform initialization from either.hpp and after that Either wrapped around json I was playing with worked as expected.

Build fails on Windows 10 using Visual C++ 2019 with Bazel

I'm using the Visual C++ 19.27.29110 compiler on Windows 10.

❯ bazel test "@com_loopperfect_neither//:all_tests"
INFO: Analyzed 4 targets (0 packages loaded, 0 targets configured).
INFO: Found 4 test targets...
ERROR: C:/tmp/yhlvxsm5/external/com_loopperfect_neither/BUILD.bazel:42:8: C++ compilation of rule '@com_loopperfect_neither//:lift_test' failed (Exit 2): cl.exe failed: error executing command
  cd C:/tmp/yhlvxsm5/execroot/__main__
  SET INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\ATLMFC\include;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\include;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\winrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\cppwinrt
    SET PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\\Extensions\Microsoft\IntelliCode\CLI;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\bin\HostX64\x64;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\VC\VCPackages;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\bin\Roslyn;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Team Tools\Performance Tools\x64;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Team Tools\Performance Tools;C:\Program Files (x86)\Microsoft Visual Studio\Shared\Common\VSPerfCollectionTools\vs2019\\x64;C:\Program Files (x86)\Microsoft Visual Studio\Shared\Common\VSPerfCollectionTools\vs2019\;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64\;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\FSharp\;C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64;C:\Program Files (x86)\Windows Kits\10\bin\x64;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\\MSBuild\Current\Bin;C:\Windows\Microsoft.NET\Framework64\v4.0.30319;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\;;C:\WINDOWS\system32;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\VC\Linux\bin\ConnectionManagerExe
    SET PWD=/proc/self/cwd
    SET TEMP=C:\Users\yesudeep\AppData\Local\Temp
    SET TMP=C:\Users\yesudeep\AppData\Local\Temp
  C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.27.29110/bin/HostX64/x64/cl.exe /nologo /DCOMPILER_MSVC /DNOMINMAX /D_WIN32_WINNT=0x0601 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS /bigobj /Zm500 /EHsc /wd4351 /wd4291 /wd4250 /wd4996 /Iexternal/com_loopperfect_neither /Ibazel-out/x64_windows-fastbuild/bin/external/com_loopperfect_neither /Iexternal/com_google_googletest /Ibazel-out/x64_windows-fastbuild/bin/external/com_google_googletest /Iexternal/bazel_tools /Ibazel-out/x64_windows-fastbuild/bin/external/bazel_tools /Ibazel-out/x64_windows-fastbuild/bin/external/com_loopperfect_neither/_virtual_includes/neither /Iexternal/com_loopperfect_neither/neither/include /Ibazel-out/x64_windows-fastbuild/bin/external/com_loopperfect_neither/neither/include /Iexternal/com_google_googletest/googlemock /Ibazel-out/x64_windows-fastbuild/bin/external/com_google_googletest/googlemock /Iexternal/com_google_googletest/googlemock/include /Ibazel-out/x64_windows-fastbuild/bin/external/com_google_googletest/googlemock/include /Iexternal/com_google_googletest/googletest /Ibazel-out/x64_windows-fastbuild/bin/external/com_google_googletest/googletest /Iexternal/com_google_googletest/googletest/include /Ibazel-out/x64_windows-fastbuild/bin/external/com_google_googletest/googletest/include /showIncludes /MD /Od /Z7 /wd4117 -D__DATE__="redacted" -D__TIMESTAMP__="redacted" -D__TIME__="redacted" -DHAVE_BAZEL_BUILD /DHAVE_BAZEL_BUILD_WINDOWS /D_HAS_DEPRECATED_RESULT_OF=1 /std:c++latest /Fobazel-out/x64_windows-fastbuild/bin/external/com_loopperfect_neither/_objs/lift_test/lift.obj /c external/com_loopperfect_neither/neither/tests/lift.cpp
Execution platform: @local_config_platform//:host
C:\tmp\yhlvxsm5\execroot\__main__\bazel-out\x64_windows-fastbuild\bin\external\com_loopperfect_neither\_virtual_includes\neither\neither/either.hpp(149): error C2560: 'common_type<L2,R2>::type neither::Either<L,R>::join(void) &&': cannot overload a member function with ref-qualifier with a member function without ref-qualifier
C:\tmp\yhlvxsm5\execroot\__main__\bazel-out\x64_windows-fastbuild\bin\external\com_loopperfect_neither\_virtual_includes\neither\neither/either.hpp(304): note: see reference to class template instantiation 'neither::Either<L,R>' being compiled
INFO: Elapsed time: 2.906s, Critical Path: 1.80s
INFO: 0 processes.
FAILED: Build did NOT complete successfully
@com_loopperfect_neither//:either_test                                NO STATUS
@com_loopperfect_neither//:maybe_test                                 NO STATUS
@com_loopperfect_neither//:try_test                                   NO STATUS
@com_loopperfect_neither//:lift_test                            FAILED TO BUILD

FAILED: Build did NOT complete successfully

Bazel build file for reference:

load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")

licenses(["notice"])  # MIT License

exports_files(["LICENSE.txt"])

cc_library(
    name = "neither",
    hdrs = [
        "neither/include/either.hpp",
        "neither/include/lift.hpp",
        "neither/include/maybe.hpp",
        "neither/include/neither.hpp",
        "neither/include/traits.hpp",
        "neither/include/try.hpp",
    ],
    include_prefix = "neither",
    includes = ["neither/include"],
    linkstatic = True,
    strip_include_prefix = "neither/include",
    visibility = ["//visibility:public"],
)

test_suite(
    name = "all_tests",
    tests = [
        ":either_test",
        ":lift_test",
        ":maybe_test",
        ":try_test",
    ],
)

cc_test(
    name = "either_test",
    size = "small",
    srcs = [
        "neither/tests/either.cpp",
    ],
    deps = [
        ":neither",
        "@com_google_googletest//:gtest_main",
    ],
)

cc_test(
    name = "lift_test",
    size = "small",
    srcs = [
        "neither/tests/lift.cpp",
    ],
    deps = [
        ":neither",
        "@com_google_googletest//:gtest_main",
    ],
)

cc_test(
    name = "maybe_test",
    size = "small",
    srcs = [
        "neither/tests/maybe.cpp",
    ],
    deps = [
        ":neither",
        "@com_google_googletest//:gtest_main",
    ],
)

cc_test(
    name = "try_test",
    size = "small",
    srcs = [
        "neither/tests/try.cpp",
    ],
    deps = [
        ":neither",
        "@com_google_googletest//:gtest_main",
    ],
)

implement lift

int add(int x, int y) {
  return x+y;
}

auto x = maybe(1);
auto y = maybe(2);

auto maybeAdd = lift(add);
auto maybeZ = maybeAdd(x, y);

No license defined

I would really like to use this implementation in my project but there is no license defined. Without it standard copyright laws hold. Is there any chance for some permissive license?

Implement iterator api

A Maybe is a container like vector but has either 0 or 1 element.
This would be convenient:

for(auto x : maybe(1) ) {
  std::cout << x << std::endl; // prints 1
} 

for(auto x : maybe<int>() ) {
  //loop not entered
} 

Functional maps should never have sideeffects. For sideeffects this way should be preferred.

Possibly revert #30

Hey neither developers, Hey @nikhedonia,

so I contributed #30 some time ago and promised to implement some move specializations for neither::Maybe which I just started. However, I was not a 100% convinced of my implementation for Eithers at that time and now ran into more issues with neither::Maybe. Mostly that the hasValue attribute needed to be mutable now.

My main concern is that pull #30 introduced mutations to Eithers, which are not directly visible to the developer. Given that a stored value is not copy-constructible the Either would lose its value on map & join. At that time I thought this was the pill one had to swallow to work with unique_ptrs in lvalues.

Now it dawned on me that you can always std::move the object to retrieve an rvalue again.
Here is a very minimal example:

TEST(neither, either_fromLvalueByMove) {
  neither::Either<std::unique_ptr<int>, int> e = left(std::make_unique<int>(0));
  std::move(e).leftMap([](auto ptr) {
    EXPECT_EQ(*ptr, 0);
    return std::move(ptr);
    });
}

From my POV this is much more clear as it shows clearly that e is potentially no longer usable after this operation. Therefore I would suggest to revert this pull and to just add some documentation on some common and niche use cases to the documentation.

Kind regards
Tilmann

make Either constexpr if possible

Currently either is never constexpr because it implements a destructor.
This is needed in the generic case as the types for left or right might have a custom destructor.
Using type_traits we can test if this is the case and make Either a literal type(constexpr) if we deal with pods only.

Incorrect copy constructors

The copy constructors,

constexpr Either( Either<L, R> const& e )
  : isLeft(e.isLeft) {
  if(isLeft) {
    leftValue = e.leftValue;
  } else {
    rightValue = e.rightValue;
  }
}
constexpr Maybe(Maybe<T> const &o) : hasValue{o.hasValue} {
  if (o.hasValue) {
    value = o.value;
  }
}

Are not implemented correctly see: https://stackoverflow.com/q/44316175/1104294. this->leftValue this->rightValue, and this->value are being directly assigned to instead of copy-constructed as they should be.

Move Semantics for Either

We should have an overload for move semantics for either.
However we need to be careful here. Move mutates the state of the referenced object by making it potentially invalid.
In case of an Either this should be only allowed if Either itself is movable to make Either behave like an valuetype.

In c++ this semantics can be expressed via:

#include <iostream>
#include <string>

struct Test {
    constexpr int get() const& { return 1; }   
    constexpr int get()&& { return 0; }    // if object is a temporary
};

int main()
{
    Test x;
    std::cout << "const&, " << x.get() << "!\n";
    std::cout << "&& " << Test{}.get() << "!\n";
}

// http://cpp.sh/6tnb6

Why is this Important? - consider the following example:

Eiher<int, unique_ptr<int>> e = right(make_unique(5));

auto e2 = e.rightMap([](auto&& ptr) { return ptr; });
auto e3 = e.rightMap([](auto&& ptr) { return ptr; });

e2.rightMap([](auto&& ptr) { return ptr.get() == 5; }); // right(true);
e2.rightMap([](auto&& ptr) { return ptr.get() == 5; }); // segfault: ptr is not valid anymore

neither composable.

Hi,

I assumed that it should be composable, i.e. something like should work:

struct my_error_t {
    std::string s;
};

struct struct_a {
    int v;
};

struct struct_b {
    double v;
};

neither::Either<my_error_t, struct_a> f1();

neither::Either<my_error_t, struct_b> f2();


void code() {
    auto value = f1()
        .rightMap([](const struct_a& v){
            return f2();
        })
        .rightMap([](const struct_b& v){
            return 5;
        })
        .leftMap([](const auto& my_error){
            return 6;
        }).join();
    // value should be either 5 or 6
}

To let it compile, I have to write something like :

    auto value = f1()
        .rightMap([](const struct_a& v){
            return f2();
        })
        .rightMap([](const auto& v){
            return v.rightMap([](const struct_b& v){
                return 5;
            })
            .leftMap([](const auto& my_error){
                return 6;
            });
        })
        .leftMap([](const auto& my_error){
            return 6;
        }).join();
    // value should be either 5 or 6

what is the sense of the library if it is not composable, i.e. forces me to unwrap in the next right_map the monadic result of the previous right_map and duplicate errors handling ?

WBR,
basiliscos

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.