gpt4 book ai didi

haskell - 如何调用可能失败的构造函数,尤其是在实现 'Read' 和 'Arbitrary' 时?

转载 作者:行者123 更新时间:2023-12-03 07:50:00 26 4
gpt4 key购买 nike

我有一个“公共(public)保险箱”,可能会因(可能提供信息的)错误而失败:

data EnigmaError = BadRotors
| BadWindows
| MiscError String

instance Show EnigmaError where
show BadRotors = "Bad rotors"
show BadWindows = "Bad windows"
show (MiscError str) = str

configEnigma :: String -> String -> String -> String -> Except EnigmaError EnigmaConfig
configEnigma rots winds plug rngs = do
unless (and $ [(>=1),(<=26)] <*> rngs') (throwError BadRotors)
unless (and $ (`elem` letters) <$> winds') (throwError BadWindows)
-- ...
return EnigmaConfig {
components = components',
positions = zipWith (\w r -> (mod (numA0 w - r + 1) 26) + 1) winds' rngs',
rings = rngs'
}
where
rngs' = reverse $ (read <$> (splitOn "." $ "01." ++ rngs ++ ".01") :: [Int])
winds' = "A" ++ reverse winds ++ "A"
components' = reverse $ splitOn "-" $ rots ++ "-" ++ plug

但不清楚我应该如何称呼它,特别是(特别是)在实现 Read 时和 Arbitrary (用于快速检查)。

对于前者,我可以做到
instance Read EnigmaConfig where
readsPrec _ i = case runExcept (configEnigma c w s r) of
Right cfg -> [(cfg, "")]
Left err -> undefined
where [c, w, s, r] = words i

但这似乎最终隐藏了 err 中可用的错误信息;而对于后者,我被困在
instance Arbitrary EnigmaConfig where
arbitrary = do
nc <- choose (3,4) -- This could cover a wider range
ws <- replicateM nc capitals
cs <- replicateM nc (elements rotors)
uk <- elements reflectors
rs <- replicateM nc (choose (1,26))
return $ configEnigma (intercalate "-" (uk:cs))
ws
"UX.MO.KZ.AY.EF.PL" -- TBD - Generate plugboard and test <<<
(intercalate "." $ (printf "%02d") <$> (rs :: [Int]))

由于预期类型和实际类型不匹配而失败:

Expected type: Gen EnigmaConfig Actual type: Gen (transformers-0.4.2.0:Control.Monad.Trans.Except.Except Crypto.Enigma.EnigmaError EnigmaConfig)



(“公共(public)安全”)构造函数可能失败时如何调用它,尤其是在实现 Read 时使用它和 Arbitrary我的课?

最佳答案

Read typeclass 将解析表示为成功列表(失败与不成功相同);所以而不是undefined你应该返回 [] .至于丢失有关问题的信息:这是真的,readsPrec 的类型意味着您对此无能为力。如果您真的非常想要 [注意:我认为您不应该想要这个],您可以在 Except EnigmaError EnigmaConfig 周围定义一个新类型包装器。并给它一个Read成功解析配置错误的实例。

对于 Arbitrary你有几个选择。一种选择是所谓的拒绝抽样;例如

arbitrary = do
-- ...
case configEnigma ... of
Left err -> arbitrary -- try again
Right v -> return v

您也可以考虑 Arbitrary实例成为您内部 API 的一部分,并使用不安全的内部调用,而不是使用安全的公共(public) API 来构建您的配置。其他选项包括调用 errorfail . (我认为这四个选项大致按优先顺序排列——拒绝抽样,然后是不安全的内部调用,然后是 error,然后是 fail——尽管你的判断可能不同。)

关于haskell - 如何调用可能失败的构造函数,尤其是在实现 'Read' 和 'Arbitrary' 时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33724378/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com