1"use strict";(globalThis.webpackChunkzio_site||=[]).push([[7647],{71038(e,n,r){r.r(n),r.d(n,{assets:()=>i,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>t,toc:()=>l});const t=JSON.parse('{"id":"reference/error-management/operations/merging-the-error-channel-into-the-success-channel","title":"Merging the Error Channel into the Success Channel","description":"Use ZIO#merge to collapse the error channel into the success channel when the error and success types are compatible, producing an infallible effect.","source":"@site/docs/reference/error-management/operations/merging-the-error-channel-into-the-success-channel.md","sourceDirName":"reference/error-management/operations","slug":"/reference/error-management/operations/merging-the-error-channel-into-the-success-channel","permalink":"/reference/error-management/operations/merging-the-error-channel-into-the-success-channel","draft":false,"unlisted":false,"editUrl":"https://github.com/zio/zio/edit/series/2.x/docs/reference/error-management/operations/merging-the-error-channel-into-the-success-channel.md","tags":[],"version":"current","frontMatter":{"id":"merging-the-error-channel-into-the-success-channel","title":"Merging the Error Channel into the Success Channel","description":"Use ZIO#merge to collapse the error channel into the success channel when the error and success types are compatible, producing an infallible effect.","keywords":["Error Channel","Success Channel","Infallible Effect","Nothing","Merge"]},"sidebar":"reference-sidebar","previous":{"title":"Flattening Optional Error Types","permalink":"/reference/error-management/operations/flattening-optional-error-types"},"next":{"title":"Flipping Error and Success Channels","permalink":"/reference/error-management/operations/flipping-error-and-success-channels"}}');var s=r(74848),c=r(28453);const o={id:"merging-the-error-channel-into-the-success-channel",title:"Merging the Error Channel into the Success Channel",description:"Use ZIO#merge to collapse the error channel into the success channel when the error and success types are compatible, producing an infallible effect.",keywords:["Error Channel","Success Channel","Infallible Effect","Nothing","Merge"]},a=void 0,i={},l=[{value:"When to Use",id:"when-to-use",level:2}];function h(e){const n={code:"code",h2:"h2",p:"p",pre:"pre",...(0,c.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"ZIO#merge"})," collapses the error channel into the success channel, producing an infallible ",(0,s.jsx)(n.code,{children:"URIO"})," whose value is drawn from whichever channel fired. Its signature includes implicit evidence that constrains when the operation is legal:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"trait ZIO[-R, +E, +A] {\n def merge[A1 >: A](implicit ev1: E IsSubtypeOfError A1, ev2: CanFail[E]): URIO[R, A1]\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"merge"})," is only available when ",(0,s.jsx)(n.code,{children:"E"})," is a subtype of ",(0,s.jsx)(n.code,{children:"A1"}),", the common supertype of both channels. The implicit evidence ",(0,s.jsx)(n.code,{children:"E IsSubtypeOfError A1"})," enforces this at compile time, so the compiler rejects a call to ",(0,s.jsx)(n.code,{children:"merge"})," when the two types share no common supertype other than ",(0,s.jsx)(n.code,{children:"Any"}),". At runtime, if the effect succeeds it returns the success value; if it fails, it returns the error value \u2014 both surfaced through the success channel. The result is always an infallible effect (",(0,s.jsx)(n.code,{children:"URIO[R, A1]"}),"), meaning the typed error channel is eliminated entirely."]}),"\n",(0,s.jsxs)(n.p,{children:["The most common scenario is when ",(0,s.jsx)(n.code,{children:"E =:= A"})," \u2014 the error and success types are identical. The following example uses ",(0,s.jsx)(n.code,{children:"ZIO.fail"})," to produce a value whose error type and success type are both ",(0,s.jsx)(n.code,{children:"String"}),", then merges the channels into one:"]}
1),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:'import zio._\n\nval merged : ZIO[Any, Nothing, String] =\n ZIO.fail("Oh uh!") // ZIO[Any, String, Nothing]\n .merge // ZIO[Any, Nothing, String]\n'})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"merge"})," also handles the case where ",(0,s.jsx)(n.code,{children:"E"})," and ",(0,s.jsx)(n.code,{children:"A"})," are different types that share a common supertype \u2014 the result type becomes that supertype. The following example uses an ",(0,s.jsx)(n.code,{children:"AppStatus"})," sealed trait whose variants represent both success and failure outcomes, so ",(0,s.jsx)(n.code,{children:"merge"})," produces a ",(0,s.jsx)(n.code,{children:"URIO[Any, AppStatus]"})," regardless of which channel fires:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"import zio._\n\nsealed trait AppStatus\ncase object Ok extends AppStatus\ncase object Error extends AppStatus\n\n// E = Error.type, A = Ok.type \u2014 both are subtypes of AppStatus\nval status: URIO[Any, AppStatus] =\n ZIO.fail(Error: AppStatus).merge\n"})}),"\n",(0,s.jsx)(n.h2,{id:"when-to-use",children:"When to Use"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"merge"})," is useful when the typed error and success represent the same domain type \u2014 for example, an enumeration whose variants include both success and failure states \u2014 and you want to eliminate the error channel without losing the value. For cases where ",(0,s.jsx)(n.code,{children:"E"})," is a ",(0,s.jsx)(n.code,{children:"Throwable"}),", prefer ",(0,s.jsx)(n.code,{children:"ZIO#orDie"})," (which converts the error to a defect) over ",(0,s.jsx)(n.code,{children:"merge"}),": ",(0,s.jsx)(n.code,{children:"orDie"})," signals that the failure is unrecoverable and crashes the fiber, while ",(0,s.jsx)(n.code,{children:"merge"})," would surface the exception as a plain value in the success channel, which is rarely the right semantic for a ",(0,s.jsx)(n.code,{children:"Throwable"}),"."]})]})}function d(e={}){const{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},28453(e,n,r){r.d(n,{R:()=>o,x:()=>a});var t=r(96540);const s={},c=t.createContext(s);function o(e){const n=t.useContext(c);return t.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(c.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.