编辑2015这个问题及其答案已不再适用.它在C#6出现之前被问到,它具有空传播的opertor(?.),它避免了在这个问题和随后的答案中讨论的hacky-workarounds.截至2015年,在C#中,您现在应该使用Form.ActiveForm?.ActiveControl?.Name.
我一直在考虑.NET中的空传播问题,这常常导致丑陋的重复代码,如下所示:
尝试#1常用代码:
string activeControlName = null;
var activeForm = Form.ActiveForm;
if (activeForm != null)
{
var activeControl = activeForm.ActiveControl;
if(activeControl != null)
{
activeControlname = activeControl.Name;
}
}
Run Code Online (Sandbox Code Playgroud)
StackOverflow上有一些关于Maybe <T> monad的讨论,或者使用某种"if not null"扩展方法:
尝试#2,扩展方法:
// Usage:
var activeControlName = Form.ActiveForm
.IfNotNull(form => form.ActiveControl)
.IfNotNull(control => control.Name);
// Definition:
public static TReturn IfNotNull<TReturn, T>(T instance, Func<T, TReturn> getter)
where T : class
{
if (instance != null ) return getter(instance);
return null;
}
Run Code Online (Sandbox Code Playgroud)
我认为这更好,然而,重复的"IfNotNull"和lambdas会有一些语法混乱.我现在正在考虑这个设计:
尝试使用扩展方法#3,可能<T>
// Usage:
var activeControlName …Run Code Online (Sandbox Code Playgroud) monad被描述为处理IO的haskell解决方案.我想知道是否有其他方法可以用纯函数式语言处理IO.
我对Haskell相当新,并且慢慢地认为Monad的存在有问题.真实世界Haskell 警告不要使用它("再一次,我们建议你几乎总是避免使用失败!").我今天只注意到罗斯帕特森称之为"疣,而不是设计模式" 在2008年后(并似乎得到该线程颇有些协议).
在观看RalfLämmel博士谈论函数式编程的本质时,我开始理解可能导致Monad失败的紧张局势.在讲座中,Ralf讨论了向基础monadic解析器添加各种monadic效果(日志记录,状态等).许多效果需要更改基本解析器,有时还需要更改使用的数据类型.我认为向所有monad添加'fail'可能是一种妥协,因为'fail'是如此常见,你想尽可能避免更改'base'解析器(或其他).当然,某种"失败"对于解析器来说是有意义的,但并不总是,例如,put/get of State或者ask/local of Reader.
如果我可能走错了轨道,请告诉我.
我应该避免使用Monad失败吗?Monad失败的替代方案是什么?是否有任何替代monad库不包括这个"设计疣"?我在哪里可以阅读有关此设计决策的历史更多信息?
从对Haskell的温和介绍,有以下monad法则.任何人都可以直观地解释他们的意思吗?
return a >>= k = k a
m >>= return = m
xs >>= return . f = fmap f xs
m >>= (\x -> k x >>= h) = (m >>= k) >>= h
Run Code Online (Sandbox Code Playgroud)
这是我的尝试解释:
我们期望返回函数包装,a以便它的monadic性质是微不足道的.当我们将它绑定到一个函数时,没有monadic效果,它应该只传递a给函数.
将解包的输出m传递给return重新包装它.monadic性质保持不变.所以它和原来的monad一样.
将解包的值传递给f然后重新包装.monadic性质保持不变.这是我们将正常函数转换为monadic函数时所期望的行为.
我对这部法律没有解释.这确实说monad必须"几乎联想".
我正在学习monad,这是我的第一个工作(除了琐碎的monad).随意批评其中的一切无情.我对"更惯用"和"更优雅"的回应特别感兴趣.
该monad计算执行的绑定数.
data C a = C {value :: a, count :: Int} deriving (Show)
instance Monad C where
(>>=) (C x c) f = C (value $ f x) (c + 1)
return x = C x 0
add :: (Num a) => a -> a -> C a
add x y = return $ x + y
-- Simpler way to do this? foldM is obviously something different.
mysum [x] = return x
mysum (x:xs) = mysum xs …Run Code Online (Sandbox Code Playgroud) 如何在Scala中创建功能正常的可配置对象?我看过托尼莫里斯关于Readermonad 的视频,我仍然无法连接点.
我有一个硬编码的Client对象列表:
class Client(name : String, age : Int){ /* etc */}
object Client{
//Horrible!
val clients = List(Client("Bob", 20), Client("Cindy", 30))
}
Run Code Online (Sandbox Code Playgroud)
我希望Client.clients在运行时确定,可以灵活地从属性文件或数据库中读取它.在Java世界中,我定义了一个接口,实现了两种类型的源,并使用DI来分配一个类变量:
trait ConfigSource {
def clients : List[Client]
}
object ConfigFileSource extends ConfigSource {
override def clients = buildClientsFromProperties(Properties("clients.properties"))
//...etc, read properties files
}
object DatabaseSource extends ConfigSource { /* etc */ }
object Client {
@Resource("configuration_source")
private var config : ConfigSource = _ //Inject it at runtime
val clients …Run Code Online (Sandbox Code Playgroud) 我正在尝试验证无效方法的参数,但我找不到解决方案......
谁能告诉我该怎么办?
我正在尝试这样的事情:
def buildNormalCategory(user: User, parent: Category, name: String, description: String): Either[Error,Category] = {
val errors: Option[String] = for {
_ <- Option(user).toRight("User is mandatory for a normal category").right
_ <- Option(parent).toRight("Parent category is mandatory for a normal category").right
_ <- Option(name).toRight("Name is mandatory for a normal category").right
errors : Option[String] <- Option(description).toRight("Description is mandatory for a normal category").left.toOption
} yield errors
errors match {
case Some(errorString) => Left( Error(Error.FORBIDDEN,errorString) )
case None => Right( buildTrashCategory(user) )
}
}
Run Code Online (Sandbox Code Playgroud) 好吧,所以我不是Haskell程序员,但我对Haskell背后的许多想法非常感兴趣,并且我正在研究它.但是我被困在第一个方面:我似乎无法绕过Monads,这似乎是相当基础的.我知道有一百万个关于SO的问题要求解释Monads,所以我会更加具体地说明了什么在困扰我:
我读了这篇优秀的文章(Javascript中的介绍),并认为我完全了解Monads.然后我读了Monads上的维基百科条目,看到了:
多态类型(M t)→(t→M u)→(M u)的绑定操作,其中Haskell由中缀运算符表示>> =.它的第一个参数是monadic类型的值,它的第二个参数是一个函数,它从第一个参数的基础类型映射到另一个monadic类型,其结果是在其他monadic类型中.
好的,在我引用的文章中,bind是一个仅占用一个参数的函数.维基百科说两个.我认为我对Monads的理解如下:
但是肯定有一些错误,因为我的bind概念需要一个参数:一个函数.但是(根据维基百科)Haskell的绑定实际上有两个参数!我的错误在哪里?
这篇文章是有文化的Haskell.只需输入像"pad.lhs"这样的文件ghci就能运行它.
> {-# LANGUAGE GADTs, Rank2Types #-}
> import Control.Monad
> import Control.Monad.ST
> import Data.STRef
Run Code Online (Sandbox Code Playgroud)
好的,所以我能够想出如何ST用纯代码表示monad.首先,我们从我们的引用类型开始.它的具体价值并不重要.最重要的是PT s a不应该与任何其他类型同构forall s.(特别是,它既不应该同形()也不应该同形Void.)
> newtype PTRef s a = Ref {unref :: s a} -- This is defined liked this to make `toST'` work. It may be given a different definition.
Run Code Online (Sandbox Code Playgroud)
那种为s是*->*,但现在不是真的很重要.对于我们所关心的一切,它可能是多面手的.
> data PT s a where
> MkRef :: a -> PT s …Run Code Online (Sandbox Code Playgroud) monads ×10
haskell ×5
scala ×2
c# ×1
composition ×1
currying ×1
either ×1
ghc ×1
idiomatic ×1
io ×1
jquery ×1
reader-monad ×1
side-effects ×1
state ×1