(* This construct is for ML compatibility. The syntax '(typ,...,typ) ident'
is not used in F# code. Consider using 'ident<typ,...,typ>' instead. *)#nowarn"62"moduleError=typefromException={message:string;hresult:int;stacktrace:string}letexn2error:System.Exception->fromException=funex->{message=ex.Message;hresult=ex.HResult;stacktrace=ex.StackTrace}moduleMonad=(* Inspired by: Eirik Tsarpalis http://fssnip.net/7TF *)type('a,'b)flow=('a,'b)Choiceletsuccess:'a->('a,'b)flow=funx->Choice1Of2xletfailure:'b->('a,'b)flow=funx->Choice2Of2xlet(|Success|Failure|):('a,'b)flow->('a,'b)flow=idletcatch:(exn->'b)->'aAsync->('a,'b)flowAsync=funfm->async{let!x=Async.Catchmreturnmatchxwith|Successy->y|>success|Failuree->e|>f|>failure}letbind:('a->('c,'b)flow)->('a,'b)flow->('c,'b)flow=funf->function|Successx->x|>f|Failurex->x|>failurelet(>>=)mf=bindfmmoduleWeb=openMonad(* Don Syme Blog: "Introducing F# Asynchronous Workflows"
https://blogs.msdn.microsoft.com/dsyme/
2007/10/10/introducing-f-asynchronous-workflows/ *)openSystem.IOopenSystem.Nettyperequest=GET|POSTletsyncHttp:string->string=funurl->//Createthewebrequestobjectletreq=WebRequest.Createurl//Gettheresponse,synchronouslyletrsp=req.GetResponse()//Grabtheresponsestreamandareader.Cleanupwhenwe'redoneusestream=rsp.GetResponseStream()usereader=newStreamReader(stream)//Synchronousread-to-end,returningtheflowreader.ReadToEnd()letasyncHttp:string->stringAsync=funurl->async{//Createthewebrequestobjectletreq=WebRequest.Createurl//Gettheresponse,asynchronously//let!rsp=req.GetResponseAsync()(* API changes since blog post *)let!rsp=req.AsyncGetResponse()//Grabtheresponsestreamandareader.Cleanupwhenwe'redoneusestream=rsp.GetResponseStream()usereader=newStreamReader(stream)//synchronousread-to-endreturnreader.ReadToEnd()}letasyncHttp':(exn->'a)->(string*string)list->request->string->(string,'a)flowAsync=funerrorheadersrequesturl->async{//Createthewebrequestobjectletreq=WebRequest.Createurlreq.Method<-sprintf"%A"requestreq.ContentLength<-0Lreq.Timeout<-System.Threading.Timeout.Infiniteheaders|>List.iter(fun(k,v)->req.Headers.Add(k,v))//Gettheresponse,asynchronously//let!rsp=req.GetResponseAsync()(* API changes since blog post *)let!rsp=req.AsyncGetResponse()//Grabtheresponsestreamandareader.Cleanupwhenwe'redoneusestream=rsp.GetResponseStream()usereader=newStreamReader(stream)//synchronousread-to-endreturnreader.ReadToEnd()}|>Monad.catcherrormoduleTranslate=(* https://msdn.microsoft.com/en-us/library/ff512421.aspx *)openSystem.NetopenMonadopenWebtypefail=UnexpectedofError.fromExceptionletinline(=>)xy=x,yleturlenc:string->string=WebUtility.UrlEncodeleturlToken="https://api.cognitive.microsoft.com/sts/v1.0/issueToken"leturlTrans="https://api.microsofttranslator.com/v2/Http.svc/Translate"lettoken:string->(string,fail)flowAsync=funkey->letheaders=["Ocp-Apim-Subscription-Key"=>key]urlToken|>asyncHttp'(Error.exn2error>>Unexpected)headersPOSTlettext:string->string->string->string->(string,fail)flowAsync=funinputfromTagtoTagtoken->letquery=sprintf"%s?text=%s&from=%s&to=%s&contentType=text/plain"urlTrans(urlencinput)fromTagtoTagletheaders=["Authorization"=>sprintf"Bearer %s"token]query|>asyncHttp'(Error.exn2error>>Unexpected)headersGETopenMonadletapikey="omitted api key for obvious reasons"letenglish="Use pixels to express measurements for padding and margins."(* Language Tag: https://msdn.microsoft.com/en-us/library/cc233982.aspx *)leten="en"letda="da"Translate.tokenapikey|>Async.RunSynchronously|>function|Successtoken->Translate.textenglishendatoken|>Async.RunSynchronously|>printfn"%A"|Failureerror->error|>printfn"%A"