使用list comprehension在Haskell中创建一个新类型列表

pro*_*eek 0 haskell list-comprehension

我正在尝试创建一个函数,它返回我从两个列表中定义的assoc类型列表.我考虑使用列表理解,但我不确定如何从每个列表中获取值.

type Assoc k v = [(k, v)]

makeAssoc :: [k] -> [v] -> [Assoc k v]
makeAssoc k v =
   [Assoc k' v' | k' <- k, ???]

main :: IO ()
main = do
    putStrLn $ show makeAssoc [1,2,3] [4,5,6]
Run Code Online (Sandbox Code Playgroud)

如何实施makeAssoc k v

son*_*ico 5

您已将其定义Assoc k v为别名(type不创建不同的类型,只为现有类型提供新名称 - 它们仍可互换)以获取列表(k, v).根据makeAssoc类型签名,它返回一个列表Assoc k v.这意味着它实际上返回了一个列表列表,(k, v)这可能不是你想要的.两种可能的解决方

解决方案1 ​​ - 保留Assoc k v为元组列表,并从makeAssoc的类型签名中删除[]

type Assoc k v = [(k, v)]

makeAssoc :: [k] -> [v] -> Assoc k v
Run Code Online (Sandbox Code Playgroud)

解决方案2 - Assoc k v为元组(不是元组列表)创建别名,并将[]保存在makeAssoc的类型签名中

type Assoc k v = (k, v)

makeAssoc :: [k] -> [v] -> [Assoc k v]
Run Code Online (Sandbox Code Playgroud)

另一个问题是type Assoc k v创建Assoc k v可以在类型签名上使用的别名,但它不会创建具有相应数据构造函数的实际不同类型.所以你不能Assoc k v在实际的函数实现上使用.这意味着我们正在使用简单的元组,并且列表推导的正确语法将是(使用之前的第二个解决方案):

type Assoc k v = (k, v)

makeAssoc :: [k] -> [v] -> [Assoc k v]
makeAssoc ks vs = [(k, v) | k <- ks, v <- vs]
Run Code Online (Sandbox Code Playgroud)

但是列表推导将使用每个列表中的一个元素为您提供每个可能的对.例子:makeAssoc [1, 2] [3, 4]将导致[(1, 3), (1, 4), (2, 3), (2, 4)].如果你真的想要一对一的直接映射,你应该使用zip.

type Assoc k v = (k, v)

makeAssoc :: [k] -> [v] -> [Assoc k v]
makeAssoc ks vs = zip ks vs
Run Code Online (Sandbox Code Playgroud)

通过这种实现,结果将是[(1, 3), (2, 4)].

编辑:

更进一步:当您在Haskell中获得更多经验时,您将了解到您可以编写相同的内容:

type Assoc k v = (k, v)

makeAssoc :: [k] -> [v] -> [Assoc k v]
makeAssoc = zip
Run Code Online (Sandbox Code Playgroud)

另一件事:如果你想要一个实际的不同类型,你可以使用data关键字和zipWith函数.

data Assoc k v = Assoc k v
    deriving (Show)

makeAssoc :: [k] -> [v] -> [Assoc k v]
makeAssoc ks vs = zipWith Assoc ks vs
Run Code Online (Sandbox Code Playgroud)

或者省略以前的参数:

data Assoc k v = Assoc k v
    deriving (Show)

makeAssoc :: [k] -> [v] -> [Assoc k v]
makeAssoc = zipWith Assoc
Run Code Online (Sandbox Code Playgroud)

了解一下Haskell对初学者来说是一个很好的资源,应该可以帮助你理解所有这些以及更多.

  • 在最后的代码片段中,您有几个不必要的lambdas. (2认同)
  • 您可能还想建议使用`newtype` (2认同)