通常没有unwrap
这样的东西,可以考虑f
作为列表函数[]
unwrap
应该返回什么对于[_, _, _]
或更好的空列表[]
?类似的事情Maybe
,假设h
是const Nothing
,你会得到Nothing
。但是,当您尝试将unwrap
的Nothing
设置为值a
时,您的思路就会失败。你可以注意到,尝试应用pure
(重新包装的结果在仿函数),意味着你希望得到的结果总是Just
为Maybe
函子,非空的[]
等
没有为Traversable
希望渺茫实例为读者函子((->) k)
。虽然这不是证据,但朝这个方向的一个很好的证据是Prelude
中没有这样的例子。还要遍历一个函数并生成一个最终容器([]
或Maybe
),您需要将函数h
应用于该函数的任何可想象的输出,这是很多潜在的值,通常是无限多。
Prelude> traverse (\n -> if n == 42 then Nothing else Just n) [1, 2, 3]
Just [1,2,3]
Prelude> traverse (\n -> if n == 42 then Nothing else Just n) [1..]
Nothing
假设k
是Int
,所以仿函数是Int ->
,假设你有一个价值g :: Int -> Int
,让它成为\n -> if n == 42 then 0 else n
,假设你想穿越上述函数值,即遍历将Nothing
如果g
对于任何输入都输出42
,但不是。遍历无法知道(它无法访问函数的代码),所以它将不得不尝试所有的输出。
如果k
是有限的,那么您可以通过列表来遍历函数。遍历表后,您可能会产生结果。这可能不是你是谁,后:
import Data.Char
import Data.Maybe
import Data.Word
instance (Enum k, Bounded k) => Foldable ((->) k) where
foldMap h f = foldMap (h . f) domain
instance (Enum k, Bounded k, Eq k) => Traversable ((->) k) where
traverse h f = fmap (\vs k -> fromJust $ k `lookup` zip domain vs) (traverse (h . f) domain)
domain :: (Enum k, Bounded k) => [k]
domain = enumFromTo minBound maxBound
tabulate :: (Enum k, Bounded k) => (k -> a) -> [(k, a)]
tabulate f = zip domain (map f domain)
f1 :: Bool -> Int
f1 b = if b then 42 else 666
f2 :: Ordering -> Char
f2 LT = 'l'
f2 EQ = 'e'
f2 GT = 'g'
f3 :: Word8 -> Bool
f3 n = fromIntegral n < 256
f4 :: Word16 -> Bool
f4 n = fromIntegral n < 256
main = do
print (tabulate f1)
print (tabulate <$> traverse (\n -> [n, 2*n]) f1)
putStrLn ""
print (tabulate f2)
print (tabulate <$> traverse (\c -> [c, toUpper c]) f2)
putStrLn ""
print (tabulate f3)
print (tabulate <$> traverse (\b -> if b then Just b else Nothing) f3)
putStrLn ""
print (tabulate <$> traverse (\b -> if b then Just b else Nothing) f4)
首先你需要创建一个'Foldable'的实例。 – 4castle
'pure'是一个函数,而不是数据构造函数。与函数值的构造函数最接近的是lambda表达式:'\ x - > x + 1 :: Num a =>( - > a)a'。你认为你可以从这个函数中提取什么类型的'Num a => a'的值? – chepner