Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

⚖️ Trial Data Type

License

NotificationsYou must be signed in to change notification settings

kowainik/trial

Repository files navigation

GitHub CIHackageMPL-2.0 license

TheTrial Data Structure is aEither-like structure that keeps events historyinside. The data type allows to keep track of theFatality level of each suchevent entry (Warning orError).

Project Structure

This is a multi-package project that has the following packages inside:

PackageDescription
trialThe main package that contains theTrial data structure, instances and useful functions to work with the structure.
trial-optparse-applicativeTrial structure integration with theoptparse-applicative library for Command Line Interface.
trial-tomlandTrial structure integration with thetomland library for TOML configurations.
trial-exampleExample project with the usage example of theTrial data structure.

How to usetrial

trial is compatible with the latest GHC versions starting from8.6.5.

In order to start usingtrial in your project, you will need to set it up withthe three easy steps:

  1. Add the dependency ontrial in your project's.cabal file. For this, youshould modify thebuild-depends section by adding the name of this library.After the adjustment, this section could look like this:

    build-depends: base^>=4.14             , trial^>=0.0
  2. In the module where you plan to useTrial, you should add the import:

    importTrial (Trial (..),fiasco,prettyPrintTrial)
  3. Now you can use the types and functions from the library:

    main::IO()main=putStrLn$ prettyPrintTrial$ fiasco"This is fiasco, bro!"

Trial Data Structure

Let's have a closer look at theTrial data structure.Trial is a sum type that has two constructors:

  • Fiasco — represents the unsuccessful state similar to theLeftconstructor ofEither. However, unlikeLeft,Fiasco holds a list of allerror-like items that happened along the way. Each such item has a notion ofFatality (the severity of the error). The following cases coverFatality:
    • Error — fatal error that led to the final fatalFiasco.
    • Warning — non-essential error, which didn't affect the result.
  • Result — represents the successful state similar to theRightconstructor ofEither. However, unlikeRight,Result keeps the list ofallerror-like items that happened along the way. All error items arewarnings as the final result was found anyway.

Schematically,Trial has the following internal representation:

dataTrialea           │ │           │ ╰╴Resultingtype╰╴Anerroritemtype--| Unsuccessful case=Fiasco (DList (Fatality,e))╰╴Oneerroritem╰╴Levelofdamage╰╴Efficientlist-containerforerrortypeitems--| Successful case    |Result (DListe)a╰╴Result╰╴Onewarningitem╰╴Efficientlist-containerforwarningtypeitems

Trial instances

In order to follow the basis idea of the data type,Trial uses smartconstructors and different instances to make the structure work the way itworks.

Here are the main points:

  • AllFiascos can be created only with theErrorFatality level.
  • TheFatality level can be eased only through theSemigroup appends ofdifferentTrials.
  • All error items inResult should have onlyWarningFatality level. Thisis guaranteed by theTrialSemigroup andApplicative instances.
  • Semigroup is responsible for the correct collection of history events, theirFatality level and the final result decision.
  • Semigroup chooses the latest 'Result' and combines all events.
  • Think ofSemigroup instance as of high-level combinator of your result.
  • Applicative is responsible for the correct combination ofTrials.
  • Applicative returnsFiasco, if at least one value ifFiasco, combine allevents.
  • Think ofApplicative instance as of low-level combinator of your result on therecord fields level.
  • Alternative instance could help when you want to stop on the firstResult and get the history of all failures before it.
  • Alternative: return firstResult, also combine all events forallTrials before thisResult.

TaggedTrial

Additionally, there is aTrial-like data type that has a notion of thetaginside.

The main difference fromTrial is that the resulting type contains additionalinformation of the tag (or source it came from). The type looks like this:

typeTaggedTrialtaga=Trialtag (tag,a)

Due to the described instances implementation, the tag will always be alignedwith the final source it came from.

The library provides different ways to add the tag:

  • Manual with thewithTag function
  • UsingOverloadedLabelsand the providedIsLabel instance forTaggedTrial.

You can choose the one that is more suitable for your use-case.

Usage Examples

One of the use cases when one could consider usingTrial is the configurationsin the application.

If you need to collect configurations from different places, combine the resultsinto a single configuration, you can find theTrial data structure quitehandy. Withtrial you can get the event history for free and also you can keeptrack of where the final result for each component of your configurations typecomes from (by usingtag functionality).

The complete example in thetrial-example package. It combines CLI, TOMLconfiguration and the default options provided in the source code.

ExecutableDescription
trial-exampleThe basic example of config problem with the usage ofTaggedTrial
trial-example-advancedThe basic example of config problem with the usage ofTaggedTrial with thePhase based approach.

To run it you can use the following command:

$ cabal run trial-example$ cabal run trial-example-advanced

For the successful result you can use the CLI and provide necessary informationin order to have the complete configurations:

$ cabal run trial-example -- --host="abc"$ cabal run trial-example-advanced -- --host="abc"

[8]ページ先頭

©2009-2025 Movatter.jp