(* 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"
Code output:
> module Error = begin
type fromException =
{message: string;
hresult: int;
stacktrace: string;}
val exn2error : ex:System.Exception -> fromException
end
module Monad = begin
type ('a,'b) flow = Choice<'a,'b>
val success : x:'a -> ('a,'b) flow
val failure : x:'b -> ('a,'b) flow
val ( |Success|Failure| ) : (('a,'b) flow -> ('a,'b) flow)
val catch : f:(exn -> 'b) -> m:Async<'a> -> Async<('a,'b) flow>
val bind : f:('a -> ('c,'b) flow) -> _arg1:('a,'b) flow -> ('c,'b) flow
val ( >>= ) : m:('a,'b) flow -> f:('a -> ('c,'b) flow) -> ('c,'b) flow
end
module Web = begin
type request =
| GET
| POST
val syncHttp : url:string -> string
val asyncHttp : url:string -> Async<string>
val asyncHttp' :
error:(exn -> 'a) ->
headers:(string * string) list ->
request:request -> url:string -> Async<(string,'a) Monad.flow>
end
module Translate = begin
type fail = | Unexpected of Error.fromException
val inline ( => ) : x:'a -> y:'b -> 'a * 'b
val urlenc : arg00:string -> string
val urlToken : string =
"https://api.cognitive.microsoft.com/sts/v1.0/issueToken"
val urlTrans : string =
"https://api.microsofttranslator.com/v2/Http.svc/Translate"
val token : key:string -> Async<(string,fail) Monad.flow>
val text :
input:string ->
fromTag:string ->
toTag:string -> token:string -> Async<(string,fail) Monad.flow>
end
val apikey : string = "omitted api key for obvious reasons"
val english : string =
"Use pixels to express measurements for padding and margins."
val en : string = "en"
val da : string = "da"
> Choice1Of2
"<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
Brug pixel til at udtrykke målinger for polstring og margener.
</string>"
val it : unit = ()