Haskell 如何通过镜头覆盖默认值(仅当传入值不是空时)
我基本上是试图覆盖记录中的一组默认值,但前提是特定于用户的值不是Haskell 如何通过镜头覆盖默认值(仅当传入值不是空时),haskell,haskell-lens,Haskell,Haskell Lens,我基本上是试图覆盖记录中的一组默认值,但前提是特定于用户的值不是Nothing。有可能通过镜头来做吗 import qualified Data.Default as DD instance DD.Def Nouns where def = Nouns { -- default values for each field come here } lookupHStore :: HStoreList -> Text -> Maybe Text m
Nothing
。有可能通过镜头来做吗
import qualified Data.Default as DD
instance DD.Def Nouns where
def = Nouns
{
-- default values for each field come here
}
lookupHStore :: HStoreList -> Text -> Maybe Text
mkNounsFromHStoreList :: HStoreList -> Nouns
mkNounsFromHStoreList h = (DD.def Nouns)
& depSingular .~ (lookupHStore h "dep_label_singular")
-- ERROR: Won't compile because Text and (Maybe Text) don't match
使用而不是创建Default
的实例怎么样
编辑:由于您似乎还想将默认值
用于其他目的:
λ > import Data.Default
λ > import Data.Maybe
λ > :t fromMaybe def
fromMaybe def :: Default a => Maybe a -> a
这似乎就是您所追求的。使用而不是创建默认值的实例如何
编辑:由于您似乎还想将默认值
用于其他目的:
λ > import Data.Default
λ > import Data.Maybe
λ > :t fromMaybe def
fromMaybe def :: Default a => Maybe a -> a
这似乎就是你想要的。好吧,我找到了一个可能的解决方案,但我仍在寻找更好的解决方案
mkNounsFromHStoreList :: HStoreList -> Nouns
mkNounsFromHStoreList h = (DD.def Nouns)
& depSingular %~ (overrideIfJust (lookupHStore h "dep_label_singular"))
-- and more fields come here...
where
overrideIfJust val x = maybe x id val
好吧,我找到了一个可能的解决方案,但我仍在寻找更好的解决方案
mkNounsFromHStoreList :: HStoreList -> Nouns
mkNounsFromHStoreList h = (DD.def Nouns)
& depSingular %~ (overrideIfJust (lookupHStore h "dep_label_singular"))
-- and more fields come here...
where
overrideIfJust val x = maybe x id val
这似乎是我的工作。实现左偏选择-其
选择第一个非无
值
import Control.Applicative
import Data.Semigroup
data Foo = Foo {
bar :: Maybe Int,
baz :: Maybe String
}
我将为Foo
实现一个实例,它将
逐点提升到记录字段上。因此操作xy
用x
的匹配非Nothing
字段覆盖y
的字段。(您也可以使用,它也可以执行相同的操作。)
你可以用它做一件有趣的事情,就是把可能从Foo
的定义中剔除
{-# LANGUAGE RankNTypes #-}
import Control.Applicative
import Data.Semigroup
import Data.Functor.Identity
data Foo f = Foo {
bar :: f Int,
baz :: f String
}
我最初在上面写的Foo
现在相当于Foo-Maybe
。但是现在您可以表达不变量,比如“thisFoo
已填充其所有字段”,而无需复制Foo
本身
type PartialFoo = Foo Maybe -- the old Foo
type TotalFoo = Foo Identity -- a Foo with no missing values
仅依赖于可能
的备选方案
实例的半群
实例保持不变
instance Alternative f => Semigroup (Foo f) where
f1 <> f2 = Foo {
bar = bar f1 <|> bar f2,
baz = baz f1 <|> baz f2
}
现在,有了一点可遍历的启发的直截了当的废话
-- "higher order functors": functors from the category of endofunctors to the category of types
class HFunctor t where
hmap :: (forall x. f x -> g x) -> t f -> t g
-- "higher order traversables",
-- about which I have written a follow up question: https://stackoverflow.com/q/44187945/7951906
class HFunctor t => HTraversable t where
htraverse :: Applicative g => (forall x. f x -> g x) -> t f -> g (t Identity)
htraverse eta = hsequence . hmap eta
hsequence :: Applicative f => t f -> f (t Identity)
hsequence = htraverse id
instance HFunctor Foo where
hmap eta (Foo bar baz) = Foo (eta bar) (eta baz)
instance HTraversable Foo where
htraverse eta (Foo bar baz) = liftA2 Foo (Identity <$> eta bar) (Identity <$> eta baz)
对于你所需要的东西来说,这可能是过分的,但它仍然相当整洁。这似乎是一份适合你的工作。实现左偏选择-其
选择第一个非无
值
import Control.Applicative
import Data.Semigroup
data Foo = Foo {
bar :: Maybe Int,
baz :: Maybe String
}
我将为Foo
实现一个实例,它将
逐点提升到记录字段上。因此操作xy
用x
的匹配非Nothing
字段覆盖y
的字段。(您也可以使用,它也可以执行相同的操作。)
你可以用它做一件有趣的事情,就是把可能从Foo
的定义中剔除
{-# LANGUAGE RankNTypes #-}
import Control.Applicative
import Data.Semigroup
import Data.Functor.Identity
data Foo f = Foo {
bar :: f Int,
baz :: f String
}
我最初在上面写的Foo
现在相当于Foo-Maybe
。但是现在您可以表达不变量,比如“thisFoo
已填充其所有字段”,而无需复制Foo
本身
type PartialFoo = Foo Maybe -- the old Foo
type TotalFoo = Foo Identity -- a Foo with no missing values
仅依赖于可能
的备选方案
实例的半群
实例保持不变
instance Alternative f => Semigroup (Foo f) where
f1 <> f2 = Foo {
bar = bar f1 <|> bar f2,
baz = baz f1 <|> baz f2
}
现在,有了一点可遍历的启发的直截了当的废话
-- "higher order functors": functors from the category of endofunctors to the category of types
class HFunctor t where
hmap :: (forall x. f x -> g x) -> t f -> t g
-- "higher order traversables",
-- about which I have written a follow up question: https://stackoverflow.com/q/44187945/7951906
class HFunctor t => HTraversable t where
htraverse :: Applicative g => (forall x. f x -> g x) -> t f -> g (t Identity)
htraverse eta = hsequence . hmap eta
hsequence :: Applicative f => t f -> f (t Identity)
hsequence = htraverse id
instance HFunctor Foo where
hmap eta (Foo bar baz) = Foo (eta bar) (eta baz)
instance HTraversable Foo where
htraverse eta (Foo bar baz) = liftA2 Foo (Identity <$> eta bar) (Identity <$> eta baz)
对于你所需要的东西,可能做得太多了,但它仍然很整洁。你可以自己做一个组合器:
(~?) :: ASetter' s a -> Maybe a -> s -> s
s ~? Just a = s .~ a
s ~? Nothing = id
您可以像~
一样使用它:
mkNounsFromHStoreList :: HStoreList -> Nouns
mkNounsFromHStoreList h =
DD.def
& myNoun1 ~? lookupHStore h "potato"
& myNoun2 ~? lookupHStore h "cheese"
您可以制作自己的组合器:
(~?) :: ASetter' s a -> Maybe a -> s -> s
s ~? Just a = s .~ a
s ~? Nothing = id
您可以像~
一样使用它:
mkNounsFromHStoreList :: HStoreList -> Nouns
mkNounsFromHStoreList h =
DD.def
& myNoun1 ~? lookupHStore h "potato"
& myNoun2 ~? lookupHStore h "cheese"
其他事情需要默认实例,例如在UI中向用户显示默认值。对,如果需要,您仍然可以使用default
实例。我认为,为了使用默认值,您需要的函数只是fromaybe
:fromaybe def
在本上下文中应具有类型Maybe nomes->nomes
。:-)其他事情需要默认实例,例如在UI中向用户显示默认值。对,如果需要,您仍然可以使用default
实例。我认为,为了使用默认值,您需要的函数只是fromaybe
:fromaybe def
在本上下文中应具有类型Maybe nomes->nomes
。:-)你意识到了吗?overrideIfJust==flip from maybe
?你意识到了吗?overrideIfJust==flip from maybe
?我很难理解你想做什么。请包括名词
和存储列表
的定义、预期的输入/输出以及任何错误消息。我无法理解您试图执行的操作。请包括名词
和存储列表
的定义、预期输入/输出以及任何错误消息。谢谢。正是我需要的。也许应该向上游捐款。谢谢。正是我需要的。或许应该向上游捐款。