haskell - 我怎样才能使这个函数的签名更精确
问题描述
我有两个功能:
prompt :: Text -> (Text -> Either Text a) -> IO a
subPrompt :: Text -> (Text -> Bool) -> IO a -> IO (Maybe (Text, a))
subPrompt 接受第二个提示(参数 3),如果参数 2 中的函数在运行第一个提示后返回为真,则显示它。
我不喜欢的是论点 3 是IO a
我希望它更像:
subPrompt :: Text -> (Text -> Bool) -> prompt -> IO (Maybe (Text, a))
但我知道我不能那样做。我一直在想办法让签名更清楚第三个参数是什么。有什么方法可以定义更清晰的类型吗?或者也许我想多了,IO a
实际上很好 - 我对haskell很陌生。
解决方案
一种方法是将这两件事物化为数据结构。所以:
{-# LANGUAGE GADTs #-}
data Prompt a where
Prompt :: Text -> (Text -> Either Text a) -> Prompt a
SubPrompt :: Text -> (Text -> Bool) -> Prompt a -> Prompt (Maybe (Text, a))
现在,因为 to 的第三个参数SubPrompt
是 a Prompt
,所以您知道它必须是对SubPrompt
或的调用Prompt
- 绝对不是IO
可能进行文件系统访问或其他一些讨厌的事情的任意操作。
然后你可以为这个微型 DSL 编写一个解释器IO
:
runPrompt :: Prompt a -> IO a
runPrompt (Prompt cue validator) = {- what your old prompt used to do -}
runPrompt (SubPrompt cue deeper sub) = {- what your old subPrompt used to do,
calling runPrompt on sub where needed -}
除了确保您没有任意IO
作为参数SubPrompt
的好处之外,这还有一个好处是它使测试更容易。稍后您可以实现第二个完全纯的解释器;比如说,像这样的东西,它接受一个文本列表作为用户输入,并返回一个提示输出的文本列表:
data PromptResult a = Done a | NeedsMoreInput (Prompt a)
purePrompt :: Prompt a -> [Text] -> ([Text], PromptResult a)
purePrompt = {- ... -}
推荐阅读
- android - 以编程方式打开/关闭扬声器不起作用
- node.js - 如何在mongodb中的对象数组中搜索
- django - 默认 Django 密码格式的 Spring 密码编码器 (pbkdf2_sha256)
- python - 如何决定在 django fat 模型实现中放置函数的位置
- c++ - C++ 无法显示或读取整个 txt 文件
- c++ - 递归 - 我无法理解它是如何工作的
- sql - 获取时间格式“分、秒”(例如:12,56(12 分 56 秒)
- python - 我怎样才能加快这个数据帧?
- html - 在闪亮的应用程序中自定义导航栏
- reactjs - 返回时不能调用没有'new'的类构造函数