如何从类型签名实现功能?

我在 Haskell 中有以下两种类型签名:

foo :: (a -> (a,b)) -> a -> [b]

bar :: (a -> b) -> (a -> b -> c) -> a -> c

我想编写这两个函数的具体实现,但我真的很难理解从哪里开始。

我知道它foo需要一个函数(a -> (a,b))并返回a一个包含b.

bar接受一个函数(b -> c),该函数返回一个(a -> b -> c)最终返回a和的函数c

谁能告诉我一个具体实现的例子?

我怎么知道从哪里开始这样的事情以及定义的左侧是什么?

回答

你有一些误解:

我知道它foo需要一个函数(a -> (a,b))并返回a一个包含b.

不,它不会返回a。除了那个函数之外,它还期望它是另一个参数。

bar接受一个函数(b -> c),该函数返回一个(a -> b -> c)最终返回a和的函数c

同样在这里。给定g :: a -> bbar返回一个函数bar g :: (a -> b -> c) -> a -> c。这个函数反过来,给定一个函数h :: (a -> b -> c),返回一个类型为 的函数a -> c。就这样了。


这就像玩拼图:

foo :: (a -> (a,b)) -> a -> [b]
--   g   :: a -> (a,b)
--     x :: a
--   g x ::      (a,b)
foo g x = [b]  where
  (a,b) = g x

bar :: (a -> b) -> (a -> b -> c) -> a -> c
--   g   :: a -> b
--     x :: a
--   g x ::      b
--   h   :: a -> b -> c
--   h x ::      b -> c
--   h x (g x)     :: c
bar g h x = c  where
  c = ....

我们这里没有太多的自由选择。虽然,有更多方法可以获取更多类型的值b,例如foo。相反,忽视了的a(a,b) = g x,我们可以在更多的应用程序使用它g,所以其实有很多可能性在那里,就像

foo2 :: (a -> (a,b)) -> a -> [b]
foo2 g x = [b1,b2]  where
  (a1,b1) = g x
  (a2,b2) = g a1

还有很多。尽管如此,类型仍指导可能的实现。根据类型,foo甚至可以foo在其实现中使用:

foo3 :: (a -> (a,b)) -> a -> [b]
foo3 g x = b : bs  where
  (a,b) = g x
  bs = ...

所以现在,有了这个实现,前两个变成了它的特例:foo g x === take 1 (foo3 g x)foo2 g x === take 2 (foo3 g x). 拥有最一般的定义可能是最好的。


以上是如何从类型签名实现功能?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>