{"id":25180509,"url":"https://github.com/rsdc2/mars-rover","last_synced_at":"2025-04-04T04:47:00.546Z","repository":{"id":273598870,"uuid":"898930260","full_name":"rsdc2/mars-rover","owner":"rsdc2","description":"A text-based rover simulator","archived":false,"fork":false,"pushed_at":"2025-01-21T20:55:44.000Z","size":86,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-09T16:18:36.371Z","etag":null,"topics":["console-application","csharp","functional-programming"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rsdc2.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-05T10:00:09.000Z","updated_at":"2025-01-22T09:24:05.000Z","dependencies_parsed_at":"2025-01-21T21:43:37.893Z","dependency_job_id":null,"html_url":"https://github.com/rsdc2/mars-rover","commit_stats":null,"previous_names":["rsdc2/mars-rover"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsdc2%2Fmars-rover","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsdc2%2Fmars-rover/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsdc2%2Fmars-rover/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsdc2%2Fmars-rover/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rsdc2","download_url":"https://codeload.github.com/rsdc2/mars-rover/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247123098,"owners_count":20887260,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["console-application","csharp","functional-programming"],"created_at":"2025-02-09T16:18:38.456Z","updated_at":"2025-04-04T04:47:00.526Z","avatar_url":"https://github.com/rsdc2.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mars Rover\n\nThis is a console app to simulate navigating a rover across the Martian surface. The user is first asked to specify the size of the plateau to explore, and then an initial position and facing direction on that surface. The user may then provide instructions: \n\n- M = move one grid unit\n- L = rotate 90 degrees to the left\n- R = rotate 90 degrees to the right\n- Q = quit the program\n\n## Run and test in Visual Studio (2022)\n\nLoad `MarsRover.sln` in Visual Studio, from where the project can be run and tested using Visual Studio's user interface.\n\n## Running from the command line\n\n1. Clone or download the repository.\n2. `cd` into the repo folder:\n\n```\ncd mars-rover\n```\n\n3. `cd` into the `MarsRover` project.\n\n```\ncd MarsRover\n```\n\n4. Run the project:\n\n```\ndotnet run\n```\n\nThis will build and run the project. \n\n\n## Run the tests from the commandline\n\n1. `cd` into the tests folder in the repo:\n\n```\ncd MarsRover.Tests\n```\n\n2. Run the tests with:\n\n```\ndotnet test\n```\n\n## Implementation according to the functional programming paradigm\n\nI've used a pure functional approach to structuring the app. This means _inter alia_ using:\n\n- Value types instead of reference types. For example, the `MissionControl` class never changes state when the rover changes position. Instead, a new `MissionControl` class is created with a new rover each time there is a change.\n- Recursion instead of loops.\n- Monadic types from the excellent [LanguageExt](https://github.com/louthy/language-ext) library, especially `Option` and `Either`. The use of the latter means that it is never necessary to `throw` and `catch` exceptions. Instead, functions that may not succeed return an `Either\u003cstring, T\u003e`, where `T` is the return type of the corresponding non-monadic function. If the function succeeds, `T` is returned wrapped in the `Either` monad. If it fails, a `string` carrying the error message is returned, also wrapped in the `Either`. (For an introduction to the practice and advantages of functional programming in C#, see [Paul's Louth's blog](https://paullouth.com/). On monads in particular, see [his introduction](https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-7-monads/).)\n\nOne of the great benefits of wrapping return values in monadic types, like `Either`, is that it is possible to use LINQ query expressions with them. Consider the following code from the `ConsoleUI` of the `MarsRover` project:\n\n```C#\npublic static Either\u003cstring, MissionControl\u003e GetInitialSetup()\n{\n    return  from plateauSize in GetPlateauSize(None)\n            from plateau in Plateau.FromPlateauSize(plateauSize)\n            from missionControl in MissionControl.FromPlateau(plateau)\n            from position in GetInitialPosition(plateauSize, None)\n            from updatedMissionControl in missionControl.AddRover(position)\n            select updatedMissionControl;\n}\n```\n\n\nAs [Paul Louth shows](https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-7-monads/), this structure parallels `do` notation in Haskell. The equivalent function in Haskell might be written like this:\n\n```Haskell\nGetInitialSetup :: Either String MissionControl\nGetInitialSetup = do\n    plateauSize \u003c- GetPlateauSize Nothing\n    plateau \u003c- Plateau.FromPlateauSize plateauSize\n    missionControl \u003c- MissionControl.FromPlateau plateau\n    position \u003c- GetInitialPosition PlateauSize Nothing\n    updatedMissionControl \u003c- AddRover missionControl position\n    pure updatedMissionControl\n```\n\nFrom this the similarity of the structure of the two is readily apparent:\n| C#            | Haskell   |\n|---------------|------------\n| `from x in y` | x \u003c- y    |\n| `select x`    | pure x    |\n\n\n## Acknowledgements\n\n### Context\n\nThis project was written as a learning exercise as part of the [Northcoders](https://northcoders.com/) bootcamp.\n\n### Dependencies and licenses\nThe main project, `MarsRover` has one dependency:\n- [LanguageExt](https://github.com/louthy/language-ext): Extensions for functional programming in C# ([MIT](https://github.com/louthy/language-ext?tab=MIT-1-ov-file#readme))\n\nThe test project depends on:\n- [NUnit](https://github.com/nunit/nunit) ([MIT](https://github.com/nunit/nunit?tab=MIT-1-ov-file#readme))\n- [Coverlet](https://github.com/coverlet-coverage/) ([MIT](https://github.com/coverlet-coverage/coverlet?tab=License-1-ov-file))","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsdc2%2Fmars-rover","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frsdc2%2Fmars-rover","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsdc2%2Fmars-rover/lists"}