如何为具有两个参数的类型创建仿函数实例,其中两个参数必须是同一类型?
How do I create a functor instance for a type with two arguments, where both arguments have to be the same type?
我几乎已经能够为 Pair 类型创建一个有效的仿函数实例。问题是,Pair 接受两个相同类型的参数,所以当我写
fmap f (Pair a a') = Pair a (f a')
我不能保证结果是有效的 Pair,因为 (f a') 可能是任何类型。
确保此约束的 Haskell 方法是什么?
import Test.QuickCheck
import Test.QuickCheck.Function
data Pair a = Pair a a deriving (Eq, Show)
instance Functor Pair where
fmap f (Pair a a') = Pair a (f a')
-- stuff below just related to quickchecking that functor instance is valid
main = quickCheck (functorCompose' :: PFC)
type P2P = Fun Int Int
type PFC = (Pair Int) -> P2P -> P2P -> Bool
instance (Arbitrary a) => Arbitrary (Pair a) where
arbitrary = do
a <- arbitrary
b <- arbitrary
return (Pair a b)
functorIdentity :: (Functor f, Eq (f a)) => f a -> Bool
functorIdentity f = fmap id f == f
functorCompose :: (Eq (f c), Functor f) => (a -> b) -> (b -> c) -> f a -> Bool
functorCompose f g x = (fmap g (fmap f x)) == (fmap (g . f) x)
functorCompose' :: (Eq (f c), Functor f) => f a -> Fun a b -> Fun b c -> Bool
functorCompose' x (Fun _ f) (Fun _ g) = (fmap (g . f) x) == (fmap g . fmap f $ x)
这是我收到的错误消息,顺便说一句:
chap16/functor_pair.hs:22:29: Couldn't match expected type ‘b’ with actual type ‘a’ …
‘a’ is a rigid type variable bound by
the type signature for fmap :: (a -> b) -> Pair a -> Pair b
at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:3
‘b’ is a rigid type variable bound by
the type signature for fmap :: (a -> b) -> Pair a -> Pair b
at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:3
Relevant bindings include
a' :: a
(bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:18)
a :: a
(bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:16)
f :: a -> b
(bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:8)
fmap :: (a -> b) -> Pair a -> Pair b
(bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:3)
In the first argument of ‘Pair’, namely ‘a’
In the expression: Pair a (f a')
Compilation failed.
(这是来自 http://haskellbook.com/ 的练习)
假设 f :: t1 -> t2
。我们想要fmap f :: Pair t1 -> Pair t2
。您的尝试是:
fmap f (Pair a a') = Pair a (f a')
-- ^
类型错误,因为 a
的类型是 t1
而不是 t2
.
如果我们有可以将 t1
值转换为 t2
值的东西,我们可以简单地在 a
上使用它,一切都会进行类型检查。我们有这样的东西吗? ;-)
我几乎已经能够为 Pair 类型创建一个有效的仿函数实例。问题是,Pair 接受两个相同类型的参数,所以当我写
fmap f (Pair a a') = Pair a (f a')
我不能保证结果是有效的 Pair,因为 (f a') 可能是任何类型。
确保此约束的 Haskell 方法是什么?
import Test.QuickCheck
import Test.QuickCheck.Function
data Pair a = Pair a a deriving (Eq, Show)
instance Functor Pair where
fmap f (Pair a a') = Pair a (f a')
-- stuff below just related to quickchecking that functor instance is valid
main = quickCheck (functorCompose' :: PFC)
type P2P = Fun Int Int
type PFC = (Pair Int) -> P2P -> P2P -> Bool
instance (Arbitrary a) => Arbitrary (Pair a) where
arbitrary = do
a <- arbitrary
b <- arbitrary
return (Pair a b)
functorIdentity :: (Functor f, Eq (f a)) => f a -> Bool
functorIdentity f = fmap id f == f
functorCompose :: (Eq (f c), Functor f) => (a -> b) -> (b -> c) -> f a -> Bool
functorCompose f g x = (fmap g (fmap f x)) == (fmap (g . f) x)
functorCompose' :: (Eq (f c), Functor f) => f a -> Fun a b -> Fun b c -> Bool
functorCompose' x (Fun _ f) (Fun _ g) = (fmap (g . f) x) == (fmap g . fmap f $ x)
这是我收到的错误消息,顺便说一句:
chap16/functor_pair.hs:22:29: Couldn't match expected type ‘b’ with actual type ‘a’ …
‘a’ is a rigid type variable bound by
the type signature for fmap :: (a -> b) -> Pair a -> Pair b
at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:3
‘b’ is a rigid type variable bound by
the type signature for fmap :: (a -> b) -> Pair a -> Pair b
at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:3
Relevant bindings include
a' :: a
(bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:18)
a :: a
(bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:16)
f :: a -> b
(bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:8)
fmap :: (a -> b) -> Pair a -> Pair b
(bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:3)
In the first argument of ‘Pair’, namely ‘a’
In the expression: Pair a (f a')
Compilation failed.
(这是来自 http://haskellbook.com/ 的练习)
假设 f :: t1 -> t2
。我们想要fmap f :: Pair t1 -> Pair t2
。您的尝试是:
fmap f (Pair a a') = Pair a (f a')
-- ^
类型错误,因为 a
的类型是 t1
而不是 t2
.
如果我们有可以将 t1
值转换为 t2
值的东西,我们可以简单地在 a
上使用它,一切都会进行类型检查。我们有这样的东西吗? ;-)