
Roman
29.03.2017
17:38:12
Хотя как я сейчас понимаю эти два подхода не плохо комбинируются
ща
Более общим выглядит все же варирант request responce момент, анпишу где-нидь

Arseniy
29.03.2017
17:39:27
они не эквивалентны в том, что в его концепции одно событие может иметь несколько обработчиков, и каждый сам решает, хендлить или нет. а тут придётся дублировать код в ветках матча

Google

Igor
29.03.2017
17:39:29

Roman
29.03.2017
17:40:05

Igor
29.03.2017
17:40:52


Roman
29.03.2017
17:42:07
Супернавино
match strList with
| ["/start"] -> Start
|["/say"; word ] -> Say word
| ["/add"; x; y] -> (int.parse x, int parse y) |> Add
если становится сложнее, то подключаем какой-нибудь Fparsec
type Schdule =
| StartCron of CronExpression
| GetNextTimeCron
| StopCron
| InfoCron
type TGCommand =
| Start
| Showstat
| Cron of Schdule
let resultSatisfies predicate msg (p : Parser<_, _>) : Parser<_, _> =
let error = messageError msg
fun stream ->
let state = stream.State
let reply = p stream
if reply.Status <> Ok || predicate reply.Result then reply
else
stream.BacktrackTo(state) // backtrack to beginning
Reply(Error, error)
let str s : Parser<string, unit> = pstring s
let pToString p = p |>> fun x -> x.ToString()
let prange p = pipe3 p (pchar '-') p (fun a _ c -> sprintf "%s-%s" a c)
let plist (p : Parser<'a, _>) = sepBy1 p (pchar ',') |>> fun x -> System.String.Join(",", x)
let plapse (p1 : Parser<'a, _>) (p2 : Parser<'b, _>) = pipe3 p1 (pchar '/') p2 (fun a _ c -> sprintf "%s/%s" a c)
let pstar : Parser<string, unit> = pstring "*"
let pquestionMark : Parser<string, unit> = pstring "?"
let pintMinMax min max =
pint32 |> resultSatisfies (fun x -> x <= max && x >= min) (sprintf "This value must be %d-%d" min max)
let [ pfiftyNineS; ptwentyThreeS; pthirtyOneS; pelevenS; psevenS ] : list<Parser<string, unit>> =
[ pToString (pintMinMax 0 59)
pToString (pintMinMax 0 23)
pToString (pintMinMax 1 31)
pToString (pintMinMax 0 11)
pToString (pintMinMax 1 7) ]
let pcronPart (p : Parser<string, unit>) =
choice [ attempt (plapse pstar p)
attempt (plapse p p)
attempt (prange p)
(plist p)
pstar
p ]
let [ pSecOrMin; pHours; pDaysOfMonth; pMonth; pDayOfWeek ] =
[ pcronPart pfiftyNineS
pcronPart ptwentyThreeS
(pquestionMark <|> pcronPart pthirtyOneS)
pcronPart pelevenS
(pquestionMark <|> pcronPart psevenS)]
let pipe6sep p1 p2 p3 p4 p5 p6 func =
p1
>>= fun a ->
(unicodeSpaces1 >>. p2)
>>= fun b ->
(unicodeSpaces1 >>. p3)
>>= fun c ->
(unicodeSpaces1 >>. p4)
>>= fun d ->
(unicodeSpaces1 >>. p5) >>= fun e -> (unicodeSpaces1 >>. p6) >>= fun f -> preturn (func a b c d e f)
let pcron : Parser<string, unit> =
pipe6sep pSecOrMin pSecOrMin pHours pDaysOfMonth pMonth pDayOfWeek
(fun sec min h dom m dow -> System.String.Join(" ", [ sec; min; h; dom; m; dow ]))
let pstartCmd botname = str ("/start" + botname) <|> str "/start" >>% Start
let pshowstatCmd botname = str ("/showstat" + botname) <|> str "/showstat" >>% Showstat
let pcronGetTime = str "get time" >>% GetNextTimeCron
let pcronStop = str "stop" >>% StopCron
let pcronInfo = str "info" >>% InfoCron
let pcronExpression =
pcron >>= (fun x ->
try
(x |> CronExpression)
|> Schdule.StartCron
|> preturn
with :? System.FormatException as fe -> fail (fe.Message))
let pcronCmd botname =
(str ("/cron" + botname) <|> str "/cron") >>. unicodeSpaces1 >>. (pcronExpression <|> pcronGetTime <|> pcronStop <|> pcronInfo ) |>> fun x -> Cron(x)
let pcommand (botname : string) =
unicodeSpaces >>. ((pstartCmd botname) <|> (pcronCmd botname) <|> (pshowstatCmd botname))
type Schdule =
| StartCron of CronExpression
| GetNextTimeCron
| StopCron
| InfoCron
type TGCommand =
| Start
| Showstat
| Cron of Schdule
let resultSatisfies predicate msg (p : Parser<_, _>) : Parser<_, _> =
let error = messageError msg
fun stream ->
let state = stream.State
let reply = p stream
if reply.Status <> Ok || predicate reply.Result then reply
else
stream.BacktrackTo(state) // backtrack to beginning
Reply(Error, error)
let str s : Parser<string, unit> = pstring s
let pToString p = p |>> fun x -> x.ToString()
let prange p = pipe3 p (pchar '-') p (fun a _ c -> sprintf "%s-%s" a c)
let plist (p : Parser<'a, _>) = sepBy1 p (pchar ',') |>> fun x -> System.String.Join(",", x)
let plapse (p1 : Parser<'a, _>) (p2 : Parser<'b, _>) = pipe3 p1 (pchar '/') p2 (fun a _ c -> sprintf "%s/%s" a c)
let pstar : Parser<string, unit> = pstring "*"
let pquestionMark : Parser<string, unit> = pstring "?"
let pintMinMax min max =
pint32 |> resultSatisfies (fun x -> x <= max && x >= min) (sprintf "This value must be %d-%d" min max)
let [ pfiftyNineS; ptwentyThreeS; pthirtyOneS; pelevenS; psevenS ] : list<Parser<string, unit>> =
[ pToString (pintMinMax 0 59)
pToString (pintMinMax 0 23)
pToString (pintMinMax 1 31)
pToString (pintMinMax 0 11)
pToString (pintMinMax 1 7) ]
let pcronPart (p : Parser<string, unit>) =
choice [ attempt (plapse pstar p)
attempt (plapse p p)
attempt (prange p)
(plist p)
pstar
p ]
let [ pSecOrMin; pHours; pDaysOfMonth; pMonth; pDayOfWeek ] =
[ pcronPart pfiftyNineS
pcronPart ptwentyThreeS
(pquestionMark <|> pcronPart pthirtyOneS)
pcronPart pelevenS
(pquestionMark <|> pcronPart psevenS)]
let pipe6sep p1 p2 p3 p4 p5 p6 func =
p1
>>= fun a ->
(unicodeSpaces1 >>. p2)
>>= fun b ->
(unicodeSpaces1 >>. p3)
>>= fun c ->
(unicodeSpaces1 >>. p4)
>>= fun d ->
(unicodeSpaces1 >>. p5) >>= fun e -> (unicodeSpaces1 >>. p6) >>= fun f -> preturn (func a b c d e f)
let pcron : Parser<string, unit> =
pipe6sep pSecOrMin pSecOrMin pHours pDaysOfMonth pMonth pDayOfWeek
(fun sec min h dom m dow -> System.String.Join(" ", [ sec; min; h; dom; m; dow ]))
let pstartCmd botname = str ("/start" + botname) <|> str "/start" >>% Start
let pshowstatCmd botname = str ("/showstat" + botname) <|> str "/showstat" >>% Showstat
let pcronGetTime = str "get time" >>% GetNextTimeCron
let pcronStop = str "stop" >>% StopCron
let pcronInfo = str "info" >>% InfoCron
let pcronExpression =
pcron >>= (fun x ->
try
(x |> CronExpression)
|> Schdule.StartCron
|> preturn
with :? System.FormatException as fe -> fail (fe.Message))
let pcronCmd botname =
(str ("/cron" + botname) <|> str "/cron") >>. unicodeSpaces1 >>. (pcronExpression <|> pcronGetTime <|> pcronStop <|> pcronInfo ) |>> fun x -> Cron(x)
let pcommand (botname : string) =
unicodeSpaces >>. ((pstartCmd botname) <|> (pcronCmd botname) <|> (pshowstatCmd botname))
коленочный не аккуратный код
большая часть для того чтоб парсить крон, это от нечего делать.


Igor
29.03.2017
17:48:29

Roman
29.03.2017
17:48:40
https://gist.github.com/Neftedollar/6ea29f7ff8b848a799d3445778a76471'

Google

Igor
29.03.2017
17:53:03

Roman
29.03.2017
17:53:39

Igor
29.03.2017
17:54:24

Arseniy
29.03.2017
17:54:24
расширения файла укажи, типо yoba.fs

Roman
29.03.2017
17:55:03
спасибо, я думал он поймет по fs что там fs ) надо было fs.fs написать

Igor
29.03.2017
17:55:41

Roman
29.03.2017
17:57:30

Igor
29.03.2017
17:57:57

Roman
29.03.2017
17:59:06

Igor
29.03.2017
18:02:11
поясни?
Не важно. А где у тебя в коде используется TGCommand
Самое смешное что я сначала тоже сделал: type Action = List | Help | Add of string | Remove of string
и переводил строку с начало в Action, потом уже его паттернматчил.
Но во время очердного рефакторинг мне показалось это лишним действием и я дропнул его.
И теперь PM прям строку

Roman
29.03.2017
18:03:45

Igor
29.03.2017
18:04:49

Roman
29.03.2017
18:04:52
все. Дальше уже
type Schdule =
| StartCron of CronExpression
| GetNextTimeCron
| StopCron
| InfoCron
используется

Nikolay
29.03.2017
18:05:14
Спасибо за помощь, буду раскуривать

Roman
29.03.2017
18:05:25

Arseniy
29.03.2017
18:06:13
@Dolfik или почитай книжку что я сбросил, там основы на пальцах объясняются

Roman
29.03.2017
18:06:46

Google

Nikolay
29.03.2017
18:08:42

Roman
29.03.2017
18:14:10
кстати как бонус в FParsec яполучил сообщение об ошибке парсинга ) оч удобно)
оно там довольно умное

Nikolay
29.03.2017
18:18:17
А ещё такой вопрос, F# на .Net Core использует кто? У меня в 2015/2017 проект так и не получилось открыть, я так понял они поддержку ещё не допилили

Roman
29.03.2017
18:18:33

Igor
29.03.2017
18:23:07

Roman
29.03.2017
18:38:09
кстати, F# для телеграм-ботов еще не плох тем, что можно на каждый чат создавать например по актору(да в C# тоже можно но только с помощью тяжеловесной akka.net) и там например хранить состояние чата, например если писать бота для игры в крестики нолики.
Привет, всем новоприбывшим. В файлах чата можно найти полезные книги.

Arseniy
29.03.2017
19:11:05
https://twitter.com/kot_2010/status/847163223660990464

Nikolay
29.03.2017
19:14:23
Если будешь апдейт бота делать, все состояния слетят

Roman
29.03.2017
19:15:38
если же рассматривать вариант акторы для чатботов в целом, то мне кажется это очень удобно.
А если использовать akka.net или Orleans/Orleankka то там и слой персистентности сразу добавлен в реализацию акторов.

Nikolay
29.03.2017
19:18:50
Как в F# красиво сделать что-то типа такого list.Max(f => f.Id)?

Roman
29.03.2017
19:19:57

Igor
29.03.2017
19:26:17
list |> List.maxOf (fun x -> x.Id) как-то так
Надо кстати придумать более коротки синтаксис, когда что-то происходит с полем объекта,
а то это часты кейс, а выходит длиннее чем в C#
типа: list |> List.maxOf _.id |> ...
Сейчас можно делать module l = List, что бы писать list |> l.maxOf (fun x -> x.Id)

Nikolay
29.03.2017
19:30:21
У меня так получилось для IEnumerable

Google

Nikolay
29.03.2017
19:30:22
updates |> Seq.map (fun x -> x.Id ) |> Seq.max
list.Select(f => f.Id).Max() для C#

Roman
29.03.2017
19:31:58

Nikolay
29.03.2017
19:32:42

Roman
29.03.2017
19:32:50

Evgeniy
29.03.2017
19:34:32
@angmarr https://github.com/fsharp/fslang-suggestions/issues/506
Есть такое предложение.

Nikolay
29.03.2017
19:35:02

Roman
29.03.2017
19:35:23

Igor
29.03.2017
19:36:19

Roman
29.03.2017
19:39:40

Arseniy
29.03.2017
19:40:47
Так можно и до какого-нибудь J докатится

Igor
29.03.2017
19:42:34

Roman
29.03.2017
19:43:15

Evgeniy
29.03.2017
19:43:44
+

Roman
29.03.2017
19:43:54
хотя да, иногда подбешивает fun , но в целом нормально)

Vasily
29.03.2017
19:46:47

Google

Nikolay
29.03.2017
19:48:01
https://gist.github.com/Dolfik1/1b7957240813eff28c161c3572203a72
Это ужасно, да?

Vasily
29.03.2017
19:48:56
Как-то в шарповом стиле,я бы сказал

Roman
29.03.2017
19:49:02
а почему ты не хочешь воспользоваться событиями?

Igor
29.03.2017
19:49:24

Nikolay
29.03.2017
19:49:47

GNU/Patchouli
29.03.2017
19:49:48
Рекурсию надо.

Roman
29.03.2017
19:50:09

Igor
29.03.2017
19:50:37

Nikolay
29.03.2017
19:51:46

Roman
29.03.2017
19:52:14

Vasily
29.03.2017
19:52:22
Там seq.filterby,seq.iter хватит
Ну и try надо преобразовывать,конечно

Nikolay
29.03.2017
19:53:15

Roman
29.03.2017
19:53:44

Igor
29.03.2017
19:53:48

Roman
29.03.2017
19:54:08

Nikolay
29.03.2017
19:54:13
В ней проблема с переиспользованием HttpClient
https://github.com/MrRoundRobin/telegram.bot/issues/281
Разработчик не фиксит, PR не принимает, поэтому забил на неё