我在GHCI中执行以下操作:
:m + Data.Map
let map = fromList [(1, 2)]
lookup 1 map
GHCI知道map是(Map Integer Integer)。那么为什么它在Prelude.lookup和Data.Map.lookup之间声明模糊,当类型清楚时我可以避免吗?
<interactive>:1:0:
Ambiguous occurrence `lookup'
It could refer to either `Prelude.lookup', imported from Prelude
or `Data.Map.lookup', imported from Data.Map
> :t map
map :: Map Integer Integer
> :t Prelude.lookup
Prelude.lookup :: (Eq a) => a -> [(a, b)] -> Maybe b
> :t Data.Map.lookup
Data.Map.lookup :: (Ord k) => k -> Map k a -> Maybe a
答案 0 :(得分:51)
类型明显不同,但Haskell不允许临时重载名称,因此您只能选择一个lookup
而不使用前缀。
典型的解决方案是导入Data.Map
合格:
> import qualified Data.Map as Map
然后你可以说
> lookup 1 [(1,2), (3,4)]
Just 2
> Map.lookup 1 Map.empty
Nothing
通常,Haskell库要么避免重复使用Prelude中的名称,要么重新使用它们中的一大堆。 Data.Map
是其中之一,作者希望您将其导入为合格。
[编辑以包括ephemient的评论]
如果您想使用不带前缀的Data.Map.lookup
,则必须隐藏Prelude.lookup
,否则会隐式导入:
import Prelude hiding (lookup)
import Data.Map (lookup)
这有点奇怪,但如果你使用Data.Map.lookup
一堆,而你的数据结构都是地图,那么可能会很有用。
答案 1 :(得分:21)
稍微更一般地说,这首先使我感到困惑 - 所以,让我重申并强调Nathan Sanders所说的话:
Haskell不允许临时重载名称
默认情况下这是真的,但起初看起来非常明显。 Haskell允许两种样式的polymorphic functions:
参数多态是Haskell和相关语言中的标准(并且是首选的选择)方法; ad-hoc多态性是大多数其他语言的标准,通过名称如“函数重载”,并且通常通过编写具有相同名称的多个函数来实现。
在Haskell中通过类型类启用Ad-hoc多态,这需要使用所有关联的ad-hoc多态函数定义类,并为要使用的类型显式声明实例通过重载决议。 在实例声明之外定义的函数永远不是ad-hoc多态,即使它们的类型足够明显,引用也是明确的。
因此,当在不同模块中定义多个具有相同名称的非类型类函数时,如果您尝试使用任一函数,则导入两个不合格的模块将导致错误。 Data.List
,Data.Map
和Data.Set
的组合在这方面特别令人震惊,并且因为Pre Data.List
的部分由Prelude导出,所以标准做法是(作为Nathan桑德斯说,要始终导入其他合格人员。
答案 2 :(得分:0)
这总是经常发生,使用说明手册中的代码。您可以随时给他们起一个不同的名字。还要提防电子书中嵌入的unicode空间。
library IEEE;
entity log2 is
port (
clock, reset : in bit;
start : in bit;
ready : out bit;
N : in bit_vector(7 downto 0);
logval : out bit_vector (3 downto 0)
);
end entity log2;
architecture log2_arch of log2 is
component log2_UC
port (
reset, start : in bit;
clock: in bit;
ready : out bit;
N : in bit_vector(7 downto 0);
logval: in bit_vector(3 downto 0)
);
end component;
component log2_FD
port (
clock : in bit;
N : in bit_vector(7 downto 0)
);
end component;
signal entry: bit_vector(7 downto 0);
signal result: bit_vector(3 downto 0);
begin
UC: log2_UC port map (
reset => reset,
start => start,
clock => clock,
ready => ready,
N => entry,
logval => result
);
FD: log2_FD port map (
clock => clock,
N => entry
);
end architecture;
entity log2_UC is
port (
reset, start : in bit;
clock: in bit;
ready : out bit;
N : in bit_vector(7 downto 0);
logval: in bit_vector(3 downto 0)
);
end entity log2_UC;
architecture log2_UC_arch of log2_UC is
type state_t is (wait0, x1, x2, fins);
signal next_state, current_state: state_t;
begin
process(clock, reset)
begin
if reset='1' then
current_state <= wait0;
elsif (clock'event and clock='1') then
current_state <= next_state;
end if;
end process;
next_state <=
wait0 when (current_state = wait0) and (start = '0') else
x1 when (current_state = wait0) and (start = '1') else
x2 when (current_state = x1) and (logval = "1111")
;
logval <= "1111" when current_state=x1 else '0';
Ready <= '1' when current_state=fins else '0';
end log2_UC_arch;
entity log2_FD is
port (
clock : in bit;
N : in bit_vector(7 downto 0)
);
end log2_FD;
architecture archi of log2_FD is
signal reg: bit_vector(7 downto 0);
signal logval: bit_vector(3 downto 0);
signal ready: bit;
begin
process (clock)
begin
for i in 0 to 7 loop
reg(i) <= N(i);
logval <= "1111";
ready <= '0';
for i in 0 to 7 loop
nor reg(i) <= '0';
end loop;
if (clock'event and clock='1') then
for i in 7 downto 0 loop
reg(i) <= reg(i-1);
logval <= logval + 1;
end loop;
end if;
end process;
end archi;