有一个很常见的问题很容易与haskell有关。描述它的代码片段是这样的:
data JobDescription = JobOne { n :: Int }
| JobTwo
| JobThree { n :: Int }
deriving (Show, Eq)
taskOneWorker :: JobDescription -> IO ()
taskOneWorker t = do
putStrLn $ "n: " ++ (show $ n t)
main :: IO ()
main = do
-- this runs ok:
taskOneWorker (JobOne 10)
-- this fails at runtime:
-- taskOneWorker JobTwo
-- this works, but we didn't want it to:
-- taskOneWorker (JobThree 10)
我描述了这个问题,本文中可能有解决方案:https://www.fpcomplete.com/user/k_bx/playing-with-datakinds
在这里,在StackOverflow上,我想问你 - 这个问题的最佳解决方案是什么,使用哪些工具和哪些文档?
答案 0 :(得分:2)
我建议使用Prism
。 Prism
_JobOne
代表Int
构造函数中的JobOne
值。在taskOneWorker
中,我们使用^?
进行查找。值t
确实是JobOne
构造函数,其参数在Just
中返回,或者它不是JobOne
构造函数,我们返回Nothing
}。
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data JobDescription = JobOne { n :: Int }
| JobTwo
| JobThree { n :: Int }
deriving (Show, Eq)
$(makePrisms ''JobDescription)
taskOneWorker :: JobDescription -> IO ()
taskOneWorker t = do
case t ^? _JobOne of
Just n -> putStrLn $ "n: " ++ show n
Nothing -> putStrLn "Not a JobOne"
-- Or 'return ()' if you want to ignore these cases
main :: IO ()
main = do
taskOneWorker (JobOne 10)
taskOneWorker JobTwo
taskOneWorker (JobThree 10)
-- *Main> main
-- n: 10
-- Not a JobOne
-- Not a JobOne
答案 1 :(得分:-1)
耶;使用像你一样的镜头并抽象出" n"事情变成某种" JobData"对我来说似乎并不太糟糕(甚至可能还不错。)