我在试验类型签名。这里的这个是这样的:
nonz :: (Eq s, Num s, Show s) => ((->) a) s -> a -> Maybe s
nonz f v = let w = f v in if w == 0 then Nothing else Just w
main = do
print $ nonz (+3) 7
print $ nonz (+4) (-4)但当我把它变成一个典型,我就会犯一个错误:
class Nonz z where
nonz :: (Eq s, Num s, Show s) => z s -> a -> Maybe s
instance Nonz ((->) r) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w
main = do
print $ nonz (+3) 7
print $ nonz (+4) (-4)类型r和a不匹配。我怎么能把它们绑在一起?
发布于 2021-05-27 00:07:34
如果您打算将Nonz应用于带有两个参数的类型构造函数,那么您应该相应地编写类。现在,您的类参数有* -> *。很可能是你想让它有善良的* -> * -> *。
你们班
class Nonz z where
nonz :: (Eq s, Num s, Show s) => z s -> a -> Maybe s建议的备选方案
class Nonz z where
nonz :: (Eq s, Num s, Show s) => z a s -> a -> Maybe s然后可以编写您的实例。
instance Nonz (->) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w发布于 2021-05-27 08:58:05
你的代码几乎是正确的。您可以从a中的签名中移除class参数,而只需使nonz返回z (Maybe s)即可。z的内部可以隐藏a作为其实现细节的一部分。此外,Show s也不是必要的。
下面是编译的方式:
class Nonz z where
nonz :: (Eq s, Num s) => z s -> z (Maybe s)
instance Nonz ((->) a) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w
main = do
print $ nonz (+3) 7
print $ nonz (+4) (-4)这是因为a变量与Nonz类无关,因此它可以隐藏在实现中。当实现为((->) a)时,实例函数的签名将变成:
nonz :: (Eq s, Num s) => ((->) a) s -> ((->) a) (Maybe s)通过使用infix表示法和删除括号,其内容与以下内容相同:
nonz :: (Eq s, Num s) => (a -> s) -> a -> Maybe s您可能还会注意到,现在nonz的签名看起来很像函子上的一个操作。你应该是对的。通过使用此实现,您实际上可以为实现Nonz的任何类型实现Functor:
nonz' :: (Eq s, Num s) => s -> Maybe s
nonz' w = if w == 0 then Nothing else Just w
instance Nonz ((->) a) where
nonz = fmap nonz'现在您可能决定删除Nonz类,直接使用fmap nonz'。
发布于 2021-05-27 05:55:13
实际上,我想了解函数是如何成为函子实例的。所以你的回答对我很有帮助。下面是完整的工作示例:
nonz' :: (Eq s, Num s) => (a -> s) -> a -> Maybe s
{-
nonz' :: (Eq s, Num s) => ((->) a s) -> a -> Maybe s
nonz' :: (Eq s, Num s) => ((->) a) s -> a -> Maybe s
-}
nonz' f v = let w = f v in if w == 0 then Nothing else Just w
class Nonz z where
nonz :: (Eq s, Num s) => z a s -> a -> Maybe s
instance Nonz (->) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w
main = do
print $ nonz' (+3) 7
print $ nonz' (+4) (-4)
print $ nonz' length "foo"
print $ nonz' length ""
print $ nonz (+3) 7
print $ nonz (+4) (-4)
print $ nonz length "foo"
print $ nonz length ""非常感谢。
https://stackoverflow.com/questions/67713982
复制相似问题