因此,我的代码尝试读取const { Seeder } = require('mongoose-data-seed');
const mongoose = require('mongoose');
const Resource = require('../models/resource');
const SeedingHelper = require('../helpers/seeding-helper');
const { Types: { ObjectId } } = mongoose;
class ResourcesSeeder extends Seeder {
async shouldRun() { // eslint-disable-line class-methods-use-this
return Resource.count().exec().then(count => count === 0);
}
async run() { // eslint-disable-line class-methods-use-this
let result;
await SeedingHelper.readData('resourceActions')
.then((resourceActionsData) => {
const machinesId = ObjectId();
const actionTest1 = ObjectId(resourceActionsData.find(x => x.name === 'test1')._id);
const actionTest2 = ObjectId(resourceActionsData.find(x => x.name === 'test2')._id);
const data = [
{
_id: machinesId,
name: 'machines',
actions: [
actionTest1,
actionTest2,
],
},
];
result = Resource.create(data);
if (result) SeedingHelper.saveData('resources', data);
});
return result;
}
}
module.exports = ResourcesSeeder;
对并将它们转换为列表:
Int
然而,GHC抱怨说
import Control.Monad (forM, forM_)
import Data.Function (on)
import Data.List (nub)
main = do
t <- readLn
forM_ [1..t] (\_ -> do
n <- readLn
points <- forM [1..n] (\_ -> do
pointStr <- getLine
let [x, y] = map read $ words pointStr
return (x, y))
putStrLn $ if check points then "YES" else "NO")
check :: [(Int, Int)] -> Bool
check points = ((==) `on` length) (nub $ map fst points) points
我试图在 • Couldn't match type ‘(Int, Int)’ with ‘Int’
Expected type: [Int]
Actual type: [(Int, Int)]
• In the second argument of ‘(==) `on` length’, namely ‘points’
In the expression: ((==) `on` length) (nub $ map fst points) points
In an equation for ‘check’:
check points = ((==) `on` length) (nub $ map fst points) points
|
16 | check points = ((==) `on` length) (nub $ map fst points) points
| ^^^^^^
周围添加一个类型声明,但这也不起作用。如果我将read
替换为return (x, y)
,我会收到同样的错误。似乎GHC将return x
视为(x, y)
,而不是Int
。
任何帮助?
答案 0 :(得分:3)
您的问题不在于形成列表 - 错误显示第16行,这是检查功能。看着那里,我们看到:
check :: [(Int, Int)] -> Bool
check points = ((==) `on` length) (nub $ map fst points) points
注意你的相等函数的类型:
((==) `on` length) :: Foldable t => t a -> t a -> Bool
所以你需要提供两个相同类型的参数(高级注释:on
需要使用RankNTypes来允许长度应用于不同类型的参数)。但是,您提供了两种不同类型的参数([Int]
和[(Int,Int)]
)。不要试图变得花哨,只是做可读的解决方案:
length (nub (map fst points)) == length points
答案 1 :(得分:1)
错误消息告诉您问题出在check
,而不在main
中(特别是,它不与read
或{{1}有关})。更具体地说,它表示类型不匹配发生在return
的第二个参数中。既然如此,最好先了解(==) `on` length
的类型:
(==) `on` length
这告诉我们两个列表必须具有相同的元素类型,而GHCi> :t (==) `on` length
(==) `on` length :: Foldable t => t a -> t a -> Bool
- ergo&#34;无法与check
类型匹配(Int, Int)
&#34 ;. Int
接受单个任意投影函数(在您的情况下为on
),因此可以确保投影可以应用于两个参数的唯一方法是它们是否具有相同的类型: / p>
length
类型系统无法利用这样一个事实:在您的特定情况下,GHCi> :t on
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
可以应用于列表而不管元素类型如何,因此参数类型之间的差异是无关紧要的
解决这一困难的最简单方法是放弃length
:
on
或者,您可以在双方都应用check points = length (nub (map fst points)) == length points
- 元素值除了map fst
之外没有关系,所以它没有区别
nub
实现相同效果的更明确的方法是使用check points = ((==) `on` length) (nub xCoords) xCoords
where
xCoords = map fst points
中的void
,可以用来丢弃列表元素:
Data.Functor
最后,可以选择完全切换到不同的算法。这使得改进成为可能:check points = ((==) `on` length) (void . nub $ map fst points) (void points)
可以通过仅运行最短列表而不是两者来执行(如使用check
两次要求)。你可能想要实现它。为了便于说明,这是一个利用These
, the exclusive disjunction type provided by the these package的奇特解决方案。
length
import Data.List (nub)
import Data.Align (align)
import Data.These (isThese)
check :: Eq a => [(a, b)] -> Bool
check pairs = null . dropWhile isThese $ align (nub . map fst $ pairs) pairs
可以简洁地描述为贪婪的align
。如需额外评论,请参阅Does Haskell have a greedy zip (one preserving all elements)?