The idea for a startup, the working name of "where are you?".
')
The meaning is simple, the girl installs the application, indicates the number of her young man in it, and then a big button appears to send the message “where are you?” #Startup #idea
namespace Xakpc.WhereAreYou.Droid open System open Android.App open Android.Content open Android.OS open Android.Runtime open Android.Views open Android.Widget [<Activity (Label = "Xakpc.WhereAreYou.Droid", MainLauncher = true)>] type WhereAreYouActivity () = inherit Activity () let mutable count:int = 1 override this.OnCreate (bundle) = base.OnCreate (bundle) // Set our view from the "main" layout resource this.SetContentView (Resource_Layout.Main) // Get our button from the layout resource, and attach an event to it let button = this.FindViewById<Button>(Resource_Id.myButton) button.Click.Add (fun args -> button.Text <- sprintf "%d clicks!" count count <- count + 1 )
Resource.Designer.fs
file containing, as far as I understand, pointers and / or resource identifiers. In particular, there is a pointer to the Id.end identifier which is translated into the following code // aapt resource value: 0x7f070013 static member end = 2131165203
"end" (FS0010)
. And this is one of the errors that you cannot solve yourself, the management of the generation of these files is unfortunately not available to us.Alpha channel is not quite there yet yet ...
let values = ["item1"; "item2"; "item3"]
let values = ["item1"; "item2"; "item3"]
let values = ["item1"; "item2"; "item3"]
cannot be passed to the ArrayAdapter's constructor listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|] - string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn
F# - ,
F# For Fun And Profit
,
- .
hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .
Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#
. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!
Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);
.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
listView.Adapter <- new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, Android.Resource.Id.Text1, values)
, , let values = [|"item1"; "item2"; "item3"|]
- string[], list (IEnumerable )
F#. www.tryfsharp.org/Learn

F# - ,
F# For Fun And Profit
,
- .

hash
MD5 F#
let MD5Hash (input : string) = use md5 = System.Security.Cryptography.MD5.Create() input |> System.Text.Encoding.ASCII.GetBytes |> md5.ComputeHash |> Seq.map (fun c -> c.ToString("X2")) |> Seq.reduce (+)
|>
pipeline , .
: GetBytes -> -> HEX -> ( reduce + ) -> .
, C# using System; public string CreateMD5Hash (string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes (input); byte[] hashBytes = md5.ComputeHash (inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append (hashBytes[i].ToString ("X2")); } return sb.ToString(); }
: . AzureServiceWorker ( CLR )
- . F# ! Xamarin Studio .
<ItemGroup> <Compile Include="Resources\Resource.designer.fs" /> <Compile Include="Properties\AssemblyInfo.fs" /> <Compile Include="Helpers\Helpers.fs" /> <Compile Include="Services\User.fs" /> <Compile Include="Services\AzureServiceWorker.fs" /> <Compile Include="IAmHereActivity.fs" /> <Compile Include="WhereAreYouActivity.fs" /> <Compile Include="SignInActivity.fs" /> </ItemGroup>
: . Xamarin Xamarin.Mobile
. F# TPL, Task', . F# Task. , :
module Async = open System.Threading open System.Threading.Tasks let inline AwaitPlainTask (task: Task) = // rethrow exception from preceding task if it fauled let continuation (t : Task) : unit = match t.IsFaulted with | true -> raise t.Exception | arg -> () task.ContinueWith continuation |> Async.AwaitTask
Async.AwaitIAsyncResult >> Async.Ignore
let ExtractUserInfo (x : Contact) = let first = x.Phones |> Seq.tryPick(fun x -> if x.Type = PhoneType.Mobile then Some(x) else None) match first with | Some(first) -> let phone = first.Number |> StripChars [' ';'-';'(';')'] UserInfo.CreateUserInfo((MD5Hash phone), phone, x.DisplayName) | None -> UserInfo.CreateUserInfo("no mobile phone", "no mobile phone", "no mobile phone") // function for async list filling let FillContactsAsync = async { let book = new AddressBook (this) let! result = book.RequestPermission() |> Async.AwaitTask if result then _contacts <- book.ToList() |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones)) |> Seq.map ExtractUserInfo |> Seq.sortBy(fun x -> x.DisplayName) |> Seq.toList let finalContacts = _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant()) |> Seq.toArray this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, finalContacts) else System.Diagnostics.Debug.WriteLine("Permission denied by user or manifest") this.ListAdapter <- new ArrayAdapter(this, Resource_Layout.row_contact, Array.empty) }
book.ToList()
List |> Seq.filter (fun (x: Contact) -> not (Seq.isEmpty x.Phones))
|> Seq.map ExtractUserInfo
Contracts UserInfo, UserInfo |> Seq.sortBy(fun x -> x.DisplayName)
|> Seq.toList
List _contacts <-
mutable _contacts |> Seq.map (fun x -> x.DisplayName.ToUpperInvariant())<-
UserInfo string, - - |> Seq.toArray<-
List Array ArrayAdapter
- List. .

Azure Mobile Servcies
- Azure Mobile Services. NotificationHub, Push . Azure , .. .
,
module WruConstants = [<Literal>] let TotallyNotAzureServer = "https://YOUR.azure-mobile.net/"; [<Literal>] let TotallyNotAzureKey = "YOUR"
member this.RegisterMe phone name regId = async { try let table = this.MobileService.GetTable<User>() let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId } do! table.InsertAsync usr |> Async.AwaitPlainTask return (usr.Id, usr.PhoneHash, usr.Nickname) with | e -> System.Diagnostics.Trace.WriteLine(e.ToString) return (String.Empty,String.Empty,String.Empty) }
member this.RegisterMe phone name regId = async {
- ( ) . "computation expression" workflow. { } ! ( bang), do! (do-bang) let! (let bang) User. , F# ,
let usr = { Id = "" PhoneHash = MD5Hash phone Nickname = name RegistrationId = regId }
do! table.InsertAsync usr |> Async.AwaitPlainTask
do-bang, await
C#. .. continuation . return (usr.Id, usr.PhoneHash, usr.Nickname)
Tuple<string,string,string> . try ... with | e ->
try..catch
C#

. F# fst
snd
. 2 . :
let id (c,_,_) = c let phonehash (_,c,_) = c let nickname (_,_,c) = c
: id tuple
Id ..
5 Azure, Push . Azure Custom Api
exports.post = function(request, response) { // Use "request.service" to access features of your mobile service, eg: // var tables = request.service.tables; // var push = request.service.push; //response.send(statusCodes.OK, { message : 'Hello World!' }); console.log('Incoming call with requst: ', request.body.RequestId); var usersTable = request.service.tables.getTable('User'); usersTable.where( { id : request.body.TargetId } ) .read( { success: function(results) { if (results.length > 0) { var user = results[0] console.log('Send to results: ', user.Nickname, user.RegistrationId); request.service.push.gcm.send(user.RegistrationId, { RequesterId: request.body.RequesterId, RequesterNickname: request.body.RequesterName, TargetId: user.id, TargetNickname: user.Nickname }, { success: function(gcm_response) { console.log('Push notification sent: ', gcm_response); response.send(statusCodes.OK, { RequestedNickname : user.Nickname }); }, error: function(gcm_error) { console.log('Error sending push notification: ', gcm_error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : user.Nickname }); } }); } else { response.send(statusCodes.NO_CONTENT, { RequestedNickname : "" }); } }, error: function(error) { console.log('Error read table: ', error); response.send(statusCodes.INTERNAL_SERVER_ERROR, { RequestedNickname : "" }); } }); };
Push
// Perform Push operation member this.PushAsync targetId myId myNickname = async { try let (request : PushRequest) = { TargetId = targetId RequesterId = myId RequesterName = myNickname } let! result = this.MobileService.InvokeApiAsync<PushRequest, PushResponce>("pushhim", request) |> Async.AwaitTask return result.RequestedNickname with | e -> return e.ToString() }
, let-bang
do!

Google Play Services. F# . . : Xamarin.Android.Support.v7.AppCompat
, Google Play Services , .
push notification . GCM, ID, ID Push (. pushhim). BroadcastReciever developer.android.com . F# Xamarin Component Store. Google Cloud Messaging Client GCM . ID
//Check to see that GCM is supported and that the manifest has the correct information GcmClient.CheckDevice(this) GcmClient.CheckManifest(this) // check google play if CheckPlayServices() then // Try to get registration id let regId = GcmClient.GetRegistrationId this if String.IsNullOrEmpty(regId) then // Call to Register the device for Push Notifications GcmClient.Register(this, WruConstants.GcmSender);

.
, -
bitbucket.org/xakpc/whereareyou
,
, "" .
, Android F#. .
, - Android F#. , .
Source: https://habr.com/ru/post/228783/
All Articles