这段代码:
{-# LANGUAGE TypeFamilies #-}
module Study where
class C a where
type T a :: *
pred :: T a -> Bool
Run Code Online (Sandbox Code Playgroud)
- 给出这个错误:
.../Study.hs:7:5: error:
• Couldn't match type ‘T a’ with ‘T a0’
Expected type: T a -> Bool
Actual type: T a0 -> Bool
NB: ‘T’ is a type function, and may not be injective
The type variable ‘a0’ is ambiguous
• In the ambiguity check for ‘Study.pred’
To defer the ambiguity check to use sites, …Run Code Online (Sandbox Code Playgroud) 我有一个executable带有几个模块的单片包.(我所说的"单片"的意思是它的cabal文件中只有一个子句,就是这样executable.)它目前使用shell脚本以黑盒方式进行测试.我想我想为某些单独的函数编写单元测试,但cabal不同意:
% cabal new-test
cabal: Cannot test the package x-0.0.0.0 because none of the
components are available to build: the test suite 'x-test' is not
available because the solver did not find a plan that included the test suites
Run Code Online (Sandbox Code Playgroud)
以下是相关部分package.cabal:
executable x
...
other-modules: ...
...
test-suite x-test
type: exitcode-stdio-1.0
main-is: Test.hs
build-depends: base, x
hs-source-dirs: test
Run Code Online (Sandbox Code Playgroud)
我的理解是,我应该将尽可能多的模块移动到内部库,这样可以使测试套件依赖于它们.但是,我不确定维护者是否会批准这种彻底的改变.是否存在侵入性较小的方式?
我的另一个问题是,Main.hs就executable x条款而言,我们无法将其导入x-test,其中的功能(至少main)将无法进行测试.在shell脚本旁边,我应该如何测试这些函数呢?
假设我想知道文件是否存在,如果它是一个目录,还要检索其内容.我可以如下:
browseSimple :: FilePath -> IO (Either FilePath [FilePath])
browseSimple x = do
isAvailable <- doesPathExist x
if not isAvailable then error $ "File not found: " ++ x else do
isFile <- doesFileExist x
if isFile then return $ Left x else do
isDirectory <- doesDirectoryExist x
if not isDirectory then error $ "Unknown filesystem node: " ++ x else do
listing <- listDirectory x
return $ Right ((x </>) <$> listing)
-- ^
-- ? browseSimple "."
-- …Run Code Online (Sandbox Code Playgroud) 我的意思是,从定义来看:
fix f是函数的最不固定点f
换一种说法:
最不明确的
x那样f x = x.
任何nullary类型的最小定义值是undefined.这里仍有一些含糊不清,undefined可能意味着"将抛出错误"(更好)或"永远不会终止"(更糟糕).正如推理和试验所显示的那样,fix (+1)并且fix pred :: Word两者似乎都没有接近终止(即使pred 0是一个错误),因此在这两种选择之间可能总是选择"永不终止"的更糟糕的一种.(可以逃脱的fix是无聊const 1,但稍后会.)
这不是有用的应用方式fix.
有用的应用方式fix是:
fix (\f x -> if x > 7 then f (x - 1) else x)
Run Code Online (Sandbox Code Playgroud)
- 也就是说,使用fix神奇地产生递归函数.(这永远不会让我感到惊讶.)这可以被视为在两个函数之间进行选择:\f x -> f (x - 1)并且\_ x -> x,其中一个函数永远不会评估它的第一个绑定变量.这是一个危险的玩具,因为我们仍然可以得到意外地翻转即非终止了半个其领域一样容易作为一个函数> …
我希望有无数的随机或不确定的数字。我继续像这样编程:
supply :: Monad m => (Int -> m Int) -> m [Int]
supply action = sequence . fmap action $ [1..]
Run Code Online (Sandbox Code Playgroud)
-使用action为任一或\n -> randomRIO (1, n)\n -> [1.. n]
不幸的是,我无法从该供应中获取任何东西。
当我换成action与return和尝试了不同的单子,我发现Identity和Reader工作,但他们不是在这种情况下非常有用。
? flip runReader 13 (fmap (take 10) (supply return))
[1,2,3,4,5,6,7,8,9,10]
? runIdentity (fmap (take 10) (supply return))
[1,2,3,4,5,6,7,8,9,10]
? [] : (fmap (take 10) (supply return))
[[]^CInterrupted.
fmap (take 10) (supply return) :: IO [Int]
^CInterrupted. …Run Code Online (Sandbox Code Playgroud) 我的意思是:
data D = A Int | B String -- A sum type.
isA, isB :: D -> Bool -- Component predicates.
isA (A _) = True
isA _ = False
isB (B _) = True
isB _ = False
Run Code Online (Sandbox Code Playgroud)
定义起来很繁琐。当然有更好的方法。一种方法是:
data D = A Int | B String deriving (Typeable, Data)
isA', isB' :: D -> Bool
isA' x = toConstr x == toConstr (A undefined)
isB' x = toConstr x == toConstr (B undefined)
Run Code Online (Sandbox Code Playgroud)
但这需要我提供一个示例值。
有一个技巧可以用“归纳”类 …
阅读这个答案,我对第一个代码片段感到困惑:
data Pair a = P a a
instance Functor Pair where
fmap f (P x y) = P (f x) (f y)
instance Monad Pair where
return x = P x x
P a b >>= f = P x y
where P x _ = f a
P _ y = f b
Run Code Online (Sandbox Code Playgroud)
我看到的是作者重新定义数据构造 两次,并把它应用到未定义的变量.
首先,两个定义中的第二个定义P(where在instance Monad定义的条款中找到的两个定义)如果我认为第一个(我们放在第一个)总是匹配的话是怎么回事?
其次,按照什么样的语法规则可以在表达P x y的时候有没有为表达得到评估x和y范围,而是某种的 …
考虑一下这个功能reverseAndMinimum(从附近的另一个答案略微修改):
import Control.Monad.State.Strict
reverseAndMinimum' :: Ord a => [a] -> State a [a] -> State a [a]
reverseAndMinimum' [ ] res = res
reverseAndMinimum' (x:xs) res = do
smallestSoFar <- get
when (x < smallestSoFar) (put x)
reverseAndMinimum' xs ((x:) <$> res)
reverseAndMinimum :: Ord a => [a] -> ([a], a)
reverseAndMinimum [ ] = error "StateSort.reverseAndMinimum: This branch is unreachable."
reverseAndMinimum xs@(x:_) = runState (reverseAndMinimum' xs (return [ ])) x
Run Code Online (Sandbox Code Playgroud)
它只遍历一次论证; 然而,它比两次执行它的天真函数慢约30%:
reverseAndMinimum_naive :: Ord …Run Code Online (Sandbox Code Playgroud) 我有这个代码:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE DefaultSignatures #-}
module Study where
class C a where
type T a = r | r -> a
pred :: T a -> Bool
default pred :: T a ~ [a] => T a -> Bool
pred = not . null
instance C Integer where
type T Integer = [Integer]
Run Code Online (Sandbox Code Playgroud)
它的工作原理如下:
? Study.pred [1,2,3]
True
? Study.pred ([ ] :: [Integer])
False
Run Code Online (Sandbox Code Playgroud)
我想简化实例定义只是为了:
instance C Integer
Run Code Online (Sandbox Code Playgroud)
- 除非我特意要偏离模式.
我计划拥有的大多数实例应该是默认的 …