【问题标题】:Initialise values in a Haskell list初始化 Haskell 列表中的值
【发布时间】:2014-08-24 06:30:40
【问题描述】:

这里绝对是 Haskell 初学者。不太确定我在做什么。

我想创建和初始化一个配对列表,然后对它们执行某些功能。我可以这样做:

type Btype = (Char,Bool)

svar :: Char -> [Btype] -> Bool
svar x [] = False
svar x ((a,b):xs) = if (x == a) then b
                        else svar x xs

bt = [('a', True), ('b', True), ('c', False), ('d', True), ('e', False)]

这可以工作并且做我想要的,只是不是我想要的方式。

要使用此功能,我需要输入:

svar 'a' bt

我得到 True,它是标签“a”的值,所以它可以工作。

然而,我想要的是能够以某种方式初始化列表 bt,以便我可以以某种方式修改函数签名

(svar :: Char -> [Btype] -> Bool) 

所以我不必输入:

svar 'a' bt

但只需输入

svar 'a' 

并得到相同的结果。

我玩弄了 data 关键字并尝试了函数的变体,但没有运气。我似乎无法摆脱我的“程序员逻辑”并尝试从函数式编程的角度思考,这也无济于事。所以,在这里度过了一段艰难的时光。

非常感谢任何提示/提示/解决方案。谢谢。

【问题讨论】:

  • svar 函数应该如何知道要查看哪个列表?
  • 另外请注意,您基本上是在重写lookup,它的签名非常相似。
  • 很明显该函数需要列表才能工作(记住haskell是纯粹的)所以你可以做这样的事情的唯一方法就是逃到一些monad - 你可以隐藏的State/Reader-Monad你在 IO 中的价值或去 IO 并做你以前在 other 语言中做的所有事情:P
  • 您是否需要svar 来使用您在问题中所写的列表bt 以外的列表?如果没有,您可以使用 where 子句或 let 绑定将 bt 包含在 svar 的定义中。
  • 具体来说,您可以像这样实现 Keshav Kini 的建议:svar2 x = svar x bt,这将创建一个新函数 svar2,其行为与您描述的一样。

标签: haskell


【解决方案1】:

一种解决方案是使用柯里化将所需的列表bt 合并到函数中。为此,更改参数的顺序会更方便:

svar :: [Btype] -> Char -> Bool
svar [] _ = False
svar ((a,b):xs) x = if (x == a) then b
                        else svar xs x

然后用柯里化创建一个新函数:

svarbt = svar bt

现在bt 参数已内置到新函数svarbt 中。这个函数只用一个参数调用:

ghci> svarbt 'a'
True

编辑:这只是 Neil Forrester 在评论中建议的一种更复杂的方式。

【讨论】:

  • 酷,我同意了 Neil Forrester 的建议,但你的建议很有帮助,我确实花了几天时间学习 Haskell,在这个阶段任何东西都有用。谢谢。
【解决方案2】:

涉及库函数的解决方案:

import Data.List

bt :: [(Char, Bool)]
bt = [('a', True), ('b', True), ('c', False), ('d', True), ('e', False)]

svar :: Char -> Bool
svar x = maybe False snd $ find ((==x) . fst) bt

svar 读作:find the first pair 其中fst==x。这会产生Nothing is not found,或者Just somePair is found。第一种情况,返回False,第二种情况,取snd somePair

一个常见的习惯用法也是使用辅助函数,例如:(正如 Keshav Kini 建议的那样)

svar :: Char -> Bool
svar x = go bt
   where go :: [(Char, Bool)] -> Bool
         go []             = False
         go ((a,b) : rest) = if a == x then b else go rest

如果考虑效率,并且您需要在长列表中执行多次查找,则应将其转换为 Data.Map.Map(具有 O(log n) 访问权限的平衡二叉搜索树)。

import qualified Data.Map as M

btM :: M.Map Char Bool
btM = fromList bt

svar :: Char -> Bool
svar x = maybe False snd (lookup x btM)

【讨论】:

    猜你喜欢
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    相关资源
    最近更新 更多