Google |
カグア!Google Analytics 活用塾:事例や使い方 |
Twitterの投げ銭したらPayPalミーで受け取り |
https://www.kagua.biz/social/twitter/20210508.html
|
paypal |
2021-05-07 21:00:10 |
Program |
[全てのタグ]の新着質問一覧|teratail(テラテイル) |
liメニューが表示される位置を変更したい |
https://teratail.com/questions/337131?rss=all
|
liメニューが表示される位置を変更したいCSS詳しくない者です。 |
2021-05-08 06:33:18 |
Program |
[全てのタグ]の新着質問一覧|teratail(テラテイル) |
パスは指定しているのですが、Not Foundがでます。 |
https://teratail.com/questions/337130?rss=all
|
パスは指定しているのですが、NotFoundがでます。 |
2021-05-08 06:32:41 |
海外TECH |
Ars Technica |
Windows 10 “Sun Valley” will do away with Windows 95 era icons |
https://arstechnica.com/?p=1763533
|
update |
2021-05-07 21:15:58 |
海外TECH |
DEV Community |
Grokking Monad Transformers |
https://dev.to/choc13/grokking-monad-transformers-3l3
|
Grokking Monad TransformersEarlier in this series in Grokking Monads we discovered that monads allowed us to abstract away the machinery of chaining computations For example when dealing with optional values they took care of the failure path for us in the background and freed us up to just write the code as if the data was always present What happens though when we have multiple monads we d like to use how can we mix them together Just like in the rest of this series we re going to invent monad transformers ourselves by solving a real software design problem At the end we ll see that we ve discovered the monad transformer and in doing so we ll understand it more intuitively The scenarioLet s revisit the same scenario we encountered in Grokking Monads where we want to charge a user s credit card If the user exists and they have a credit card saved in their profile we can charge it and email them a receipt otherwise we ll have to signal that nothing happened This time however we re going to make the lookupUser chargeCard and emailReceipt functions async because they call external services We ll start with the following data model and operations type UserId UserId of stringtype TransactionId TransactionId of stringtype CreditCard Number string Expiry string Cvv string type User Id UserId CreditCard CreditCard option let lookupUser userId Async lt option lt User gt gt let chargeCard amount card Async lt option lt TransactionId gt gt let emailReceipt transactionId Async lt TransactionId gt The only difference from before is that lookupUser chargeCard and emailReceipt return Async now because in reality they ll be calling a database external payment gateway and sending messages Our first implementationUsing our learnings from Grokking Monads Imperatively then we might immediately reach for the async computation expression because that s the primary monad that we re dealing with here So let s start with that let chargeUser amount userId async let user lookupUser userId let card user CreditCard let transactionId chargeCard amount card return emailReceipt transactionId Looks simple and it captures the essence of what we need to do but it s not right The line let card user CreditCard isn t going to compile because at this point user is of type User option We ve also got a similar problem when writing chargeCard amount card because we ll actually have a CreditCard option there One way around this is to just start writing the pattern matching logic ourselves to get access to the values inside those options so that we can use them Let s see what that looks like let chargeUser amount userId async match lookupUser userId with Some user gt match user CreditCard with Some card gt match chargeCard amount card with Some transactionId gt return emailReceipt transactionId gt Async map Some None gt return None None gt return None None gt return None This is much more cumbersome than before and the fairly simple logic of this function is obscured by the nested pattern matching a k a the pyramid of doom We re basically back to the same situation that we found ourselves in when we first introduced this in Grokking Monads It seems like once we ve got more than one monad to deal with everything inside the outer one has to fall back to manually dealing with the failure path again through continual pattern matching Inventing a new monadAt this point we might think to ourselves why don t we invent a new monad One that encapsulates the fact that we want to perform async computations that return optional results It should behave like both the async monad when an async operation fails and the option monad when the async operation produces missing data Let s call it AsyncOption What we need to do then is figure out how to implement bind for this new monad Let s start with the types and then use them to guide us in writing it In this case it will have the signature a gt Async lt option lt b gt gt gt Async lt option lt a gt gt gt Async lt option lt b gt gt So this is telling us that we re given a function that wants some value of type a and will return us a new value wrapped up in our Async lt option lt gt gt type We re also given an instance of this monad pair that encapsulates a value of type a So intuitively we need to unwrap both the Async and option layers to get at this value of type a and then apply it to the function let bind f x async match x with Some y gt return f y None gt return None Here we ve achieved this by using the async computation expression This allows us to use a match which simultaneously unwraps the async value and pattern matches on the inner option to allow us to extract the value from that too We ve had to deal with three possible cases In the case where x is a successful async computation that s returned Some value then we can apply the function f to the value In the case that the async operation successfully returns None then we just propagate the None value by wrapping it in a new async by using return Finally if the async computation fails then we just let the async computation expression deal with that and propagate that failure without calling f So with bind in place it s easy to create an asyncOption computation expression and we can write our function using that let chargeUser amount userId asyncOption let user lookupUser userId let card user CreditCard let transactionId chargeCard amount card return emailReceipt transactionId Much better but the eagle eyed might have already spotted a problem with our plan When we try and call user CreditCard it won t work The problem is that user CreditCard returns a vanilla option and our bind and therefore let has been designed to work with Async lt option lt gt gt On top of this on the final line we have a similar problem The emailReceipt function returns a plain Async lt gt and so we can t just write return because it s not producing an Async lt option lt gt gt It seems like we re stuck with needing everything to use exactly the same monad or things won t line up Lifting ourselves out of a hole ️A simple way to solve the first problem is to just wrap that vanilla option in a default Async value What would a default Async be though Well we want to just treat it as if it s a successful async computation that s immediately resolved so let s just write a function called hoist that wraps its argument in an immediate async computation let hoist a async return a If you re a C developer this is just like Task FromResult and if you re a JavaScript developer then it s akin to Promise resolve To solve the second problem we need a way to wrap up the value inside the Async in a default option value The default option value would be Some in this case and we saw in Grokking Functors that the way to modify the contents of a wrapped value is to use map So let s create a function called lift that just calls map with Some let lift a Async lt a gt Async lt option lt a gt gt a gt Async map SomeSo with this in hand we can finally finish off our chargeUser function let chargeUser amount userId asyncOption let user lookupUser userId let card user CreditCard gt hoist let transactionId chargeCard amount card return emailReceipt transactionId gt lift This is now looking quite tidy and the logic is clear to see no longer hidden amongst nested error handling code So is that all there is to monad transformers Well not quite A combinatorial explosion Let s say for arguments sake that we wanted to use a Task instead of an Async computation Or perhaps we want to start returning a Result now instead of an option What about if we want to use a Reader too You can probably see how the combinations of all of these different monads is going to get out of hand if we need to create a new monad to represent each pair Not to mention the fact that we might want to create combinations of more than two Wouldn t it be nice if we could find a way to write a universal monad transformer One that could let us combine any two monads to create a new one Let s see if we can invent that Where do we start Well we know by now that to create a monad we need to implement bind for it We ve also seen how to do that for a new monad created from the Async and option pair of monads All we basically need to do is peel back each of monad layers to access the value contained inside the inner one and then apply this value to the function to generate a new monad pair Let s imagine for a minute that we have a universal monad computation expression which invokes the correct bind by figuring out which version to use based on the particular monad instance that it s being called on With that to hand then we should be able to peel off two monadic layers to access to the inner value quite easily let bindForAnyMonadPair f a gt Outer lt Inner lt b gt gt x Outer lt Inner lt a gt gt monad let innerMonad x monad let innerValue innerMonad return f value Unfortunately it turns out that this doesn t work The problem is that when we write return f value it s not quite right At that point in the code we re in the context of the inner monad s computation expression and so return is going to expect f to return a value that s the same as the inner monad but we know that it returns Outer lt Inner lt b gt gt because that s what we need it to have for our new bind It might seem like there would be a way out of this After all we have the value we need to supply to f so surely we must be able to just call it and generate the value we need somehow However we have to remember that computation expressions and let are just syntactic sugar for bind So what we re really trying to write is this let bindForAnyMonadPair f a gt Outer lt Inner lt b gt gt x Outer lt Inner lt a gt gt x gt bind fun innerMonad gt innerMonad gt bind fun value gt f value And then it s maybe more obvious to see that f can t be used with the inner monad s bind because it s not going to return the right type So it seems we can dig inside both monads to get to the value in a generic way but we don t have a generic way of putting them back together again There s still hope We might have failed at creating a truly universal monad transformer but we don t have to completely give up If we could make even one of the monads in the pair generic then it would massively reduce the number of monad combinations we need to write Intuitively you might think about making the inner one generic I know I did However you ll see that we fall into exactly the same trap that we did before when we tried to make both generic so that won t work In that case our only hope is to try making the outer monad generic Let s assume we ve still got our universal monad computation expression to hand and see if we can write a version that works whenever the inner monad is an option let bindWhenInnerIsOption f a gt Outer lt option lt b gt gt x Outer lt option lt a gt gt monad match option with Some value gt return f value None gt return None It works The reason we were able to succeed this time is because we could use return when calling f because we were still in the context of the outer monad s computation expression So return is able to return a value that is of the type Outer lt option lt gt gt which is precisely what f gives us back We re also going to need generic versions of hoist and lift too but they re not too difficult to write let lift x x gt map Somelet hoist result xIn order to write lift we re assuming that the Outer monad has map defined for it and that map can select the correct one because we don t know at this point in time which monad to call map on Also hoist is making use of a generic result function which is an alias for return because return is a reserved keyword in F Technically every monad should have return as well as bind defined for it We haven t mentioned return before because it s so trivial but it just wraps any plain value up in a monad For example result for option would just be Some You just discovered the Monad Transformer With our invention of bind lift and hoist for the case when inner monad is an option we ve invented the option monad transformer Normally this is called OptionT and is actually wrapped in a single case union to make it a new type which I ll show in the appendix but that s not an important detail when it comes to grokking the concept The important thing to realise is that when you need to deal with multiple monads you don t have to resort back to the pyramid of doom Instead you can use a monad transformer to represent the combination and easily create a new monad out of a pair of existing ones Just remember that it s the inner monad that we define the transformer for Test yourselfSee if you can implement bind lift and hoist for the Result monad Solution module ResultT let inline bind f a gt Monad lt Result lt b gt gt m Monad lt Result lt a gt gt monad match m with Ok value gt return f value Error e gt return Error e let inline lift x Monad lt a gt x gt map Ok let inline hoist x Result lt a e gt Monad lt Result lt a gt gt x gt result Does this actually work When we invented bind for OptionT we imagined that we had this all powerful monad computation expression to hand that would work for any monad You might be wondering if such a thing exists Particularly whether it exists in F if you re aware of the fact that F doesn t support higher kinded types which it seems like we need here in order to work with a generic outer monad type Fortunately for us the excellent FSharpPlus does have such an abstract monad computation expression defined It also has plenty of monad transformers like OptionT already defined and ready to use Should I use a monad transformer Monad transformers are certainly quite powerful and can help us recover from having to write what would otherwise be heavily nested code On the other hand though they re not exactly a free lunch There are a few things to consider before using them If the monad stack gets large it can in itself become quite cumbersome to keep track of it For instance the types can become large and the lifting across many layers can become tiring This is an area that pushes F to its limits Whilst FSharpPlus has done a fantastic job in figuring out how to emulate higher kinded types it can lead to very cryptic compile time errors if you ve got a type mismatch somewhere when using the monad transformer It can also slow down compile times due to the fact it s pushing type inference beyond what it was really designed for In some cases then you might be better off just defining a new monad and writing bind etc for it yourself If your application typically deals with the same stack of monads then the improved compiler errors will probably outweigh the relatively small maintenance burden of writing the code yourself What did we learn We ve now discovered that it s possible to combine monads into new monads and that this lets us write tidier code when we would otherwise have to write nested pattern matches We ve also seen that while it s not possible to create a universal monad transformer for any pair it is possible to at least define a monad transformer for a fixed inner type That means we only need to write one transformer per monad in order to start creating more complex monad combinations Appendix As mentioned above a monad transformer usually has a new type associated with it Below I ll show what this looks like for the OptionT monad transformer and then use that along with the generic monad computation expression from FSharpPlus to implement the chargeUser function type OptionT lt Monad lt option lt a gt gt gt OptionT of Monad lt option lt a gt gt module OptionT let run OptionT m m let inline bind f a gt Monad lt option lt b gt gt OptionT m OptionT lt Monad lt option lt a gt gt gt monad match m with Some value gt return f value None gt return None gt OptionT let inline lift x Monad lt a gt x gt map Some gt OptionT let inline hoist x a option OptionT lt Monad lt option lt a gt gt gt x gt result gt OptionTlet chargeUser amount userId Async lt option lt TransactionId gt gt monad let user lookupUser userId gt OptionT let card user CreditCard gt OptionT hoist let transactionId chargeCard amount card gt OptionT return emailReceipt transactionId gt lift gt OptionT runIf you re wondering about those type annotations like Monad lt a gt then they re really they re just fancy labels We ve used the quotations to just give a more meaningful name to show that they represent some generic Monad This acts as documentation but unfortunately it s not really doing any meaningful type checking As far as the compiler is concerned that just like any other generic type We could have easily just written type OptionT lt a gt OptionT of a So the onus is back on us when implementing these functions to make sure we do write it as if it s actually a generic monad and not just any generic value |
2021-05-07 21:29:35 |
Apple |
AppleInsider - Frontpage News |
Apple tips interest in Apple Watch blood glucose monitoring |
https://appleinsider.com/articles/21/05/07/apple-tips-interest-in-apple-watch-blood-glucose-monitoring?utm_medium=rss
|
Apple tips interest in Apple Watch blood glucose monitoringApple is reportedly surveying Apple Watch users in Brazil asking questions about eating habits medications and blood glucose level monitoring Credit Andrew O Hara AppleInsiderThe customer survey asks a slew of general questions about the Apple Watch user experience including built in health features like stand reminders and activity rings Notably it also contains questions about third party health features Read more |
2021-05-07 21:50:40 |
Apple |
AppleInsider - Frontpage News |
128M iOS users were affected by 2015 XcodeGhost malware |
https://appleinsider.com/articles/21/05/07/128m-ios-users-were-affected-by-2015-xcodeghost-malware?utm_medium=rss
|
M iOS users were affected by XcodeGhost malwareA total of million iOS users downloaded apps that were affected by the XcodeGhost malware in according to emails revealed during the Epic Games v Apple trial Credit AppleInsiderThe XcodeGhost malware was parsed into otherwise legitimate applications to mine user data in a coordinated campaign in Although the malware was quickly stopped details about the full impact of the attack remained murky Read more |
2021-05-07 21:04:48 |
海外TECH |
WIRED |
Trump Abused the System. Facebook Created It |
https://www.wired.com/story/trump-abused-the-system-facebook-created-it
|
Trump Abused the System Facebook Created ItThe company s oversight board failed to mention one thing in its ruling this week Facebook s responsibility for making the tools to wield undue influence and power |
2021-05-07 21:45:34 |
海外TECH |
WIRED |
22 Last-Minute Mother’s Day Gifts on Sale Now |
https://www.wired.com/story/last-minute-mothers-day-gift-ideas-deals-2021
|
recommended |
2021-05-07 21:10:00 |
ニュース |
BBC News - Home |
Elections results 2021: Conservatives make gains on English councils |
https://www.bbc.co.uk/news/uk-politics-57021276
|
starmer |
2021-05-07 21:29:47 |
ニュース |
BBC News - Home |
Scottish election 2021: Liberal Party member suspended over Yousaf confrontation |
https://www.bbc.co.uk/news/uk-scotland-scotland-politics-57025065
|
pakistan |
2021-05-07 21:24:04 |
ニュース |
BBC News - Home |
Leicester City 2-4 Newcastle United: Callum Wilson double in Magpies win |
https://www.bbc.co.uk/sport/football/56938827
|
leicester |
2021-05-07 21:28:36 |
ニュース |
BBC News - Home |
Murray to practise with Djokovic and hopes to be fit for French Open |
https://www.bbc.co.uk/sport/tennis/57032348
|
djokovic |
2021-05-07 21:31:29 |
ニュース |
BBC News - Home |
MacGinty kicks in-form Sale to victory against Leicester |
https://www.bbc.co.uk/sport/rugby-union/56992660
|
leicester |
2021-05-07 21:17:24 |
北海道 |
北海道新聞 |
NY株最高値、229ドル高 3日連続、緩和継続期待で |
https://www.hokkaido-np.co.jp/article/541399/
|
連続 |
2021-05-08 06:13:29 |
北海道 |
北海道新聞 |
再発防止へ、安全な散歩指導も 大津の園児死傷事故から2年 |
https://www.hokkaido-np.co.jp/article/541400/
|
再発防止 |
2021-05-08 06:03:00 |
ビジネス |
東洋経済オンライン |
日本発の新世代「3Dプリンター」がもたらす革命 トヨタも注目のベンチャーが変えるものづくり | スマホ・ガジェット | 東洋経済オンライン |
https://toyokeizai.net/articles/-/426948?utm_source=rss&utm_medium=http&utm_campaign=link_back
|
工作機械 |
2021-05-08 06:30:00 |
コメント
コメントを投稿