递归地添加给定N次的列表

时间:2016-02-18 00:06:33

标签: haskell

我尝试创建一个给定数字和列表的函数,将给定的数字添加到列表中并减少该数字。执行此操作直到数字达到0并返回列表。

IE" incList 5 []"应该返回[5,4,3,2,1]

这是我到目前为止的代码

incList :: Int -> [a] -> [a]
incList 0 xs = []
incList g [] = []
incList g (x:xs) = g:x ++ incList (g-1) (xs)

我正在使用' a'因为我希望列表以后包含任何内容。

我目前收到此错误:

    Couldn't match expected type ‘[a]’ with actual type ‘a’
  ‘a’ is a rigid type variable bound by
      the type signature for incList :: Int -> [a] -> [a]
      at incList.hs:1:12
Relevant bindings include
  xs :: [a] (bound at incList.hs:4:14)
  x :: a (bound at incList.hs:4:12)
  incList :: Int -> [a] -> [a] (bound at incList.hs:2:1)
In the first argument of ‘(++)’, namely ‘x’
In the second argument of ‘(:)’, namely ‘x ++ incList (g - 1) (xs)’

2 个答案:

答案 0 :(得分:2)

据我所知,您希望预先挂起一个列表,其中包含从某个起始值开始倒数的数值。第一次尝试时会出现几种类型和逻辑错误:

incList :: Int -> [a] -> [a]

首先,您说您的起始值是Int,但您的列表包含任何值(通过a类型变量)。您不能拥有混合类型Inta的列表,因此您必须以某种方式统一这些类型。

要明确的是,你说“我正在使用'a',因为我希望列表包含以后的任何内容。”但这不是一个有效的选项 - 列表必须只包含一种类型,而您似乎决定使用数字。

继续,我们开始使用自定义递归函数。制作你自己的很好,只要知道这可以通过内置函数或语法糖来处理。

incList 0 xs = []
incList g [] = []

你的第一个基础是好的,但是第二个基本情况,不是那么多。您明确说incList 5 []不应该是[]而是[5,4,3,2,1]那么你如何放弃第二个案例。

incList g (x:xs) = g:x ++ incList (g-1) (xs)

在这里,你为什么要解构原始列表(x:xs)。我认为你想要预先挂起值,而不是取消值并将新值与旧值混合。

此外,表达式g:x ++毫无意义。 x不是列表,因此g : x也不是(++) :: Int -> Int -> Int,因此它们没有为g : x : incList ...提供有效参数,您可能会选择incList :: Int -> [Int] -> [Int] incList 0 xs = xs incList g xs = g : incList (g-1) xs

随着这些变化,我们到达:

incList g xs = [g,g-1..1] ++ xs

这几乎与:

相同
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApplication1.resoureces">
    <SolidColorBrush x:Key="GlyphBrush" Color="#444" />
    <Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ToggleButton">
                    <Grid Width="15" Height="13" Background="Transparent">
                        <Path x:Name="ExpandPath" HorizontalAlignment="Left"  VerticalAlignment="Center"  Margin="1,1,1,1" Fill="{StaticResource GlyphBrush}" Data="M 4 0 L 8 4 L 4 8 Z"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="True">
                            <Setter Property="Data" TargetName="ExpandPath" Value="M 0 4 L 8 4 L 4 8 Z"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="TreeViewItemFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Border>
                        <Rectangle Margin="0,0,0,0" StrokeThickness="5" Stroke="Black" StrokeDashArray="1 2" Opacity="0"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="{x:Type TreeViewItem}" TargetType="{x:Type TreeViewItem}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="Padding" Value="1,0,0,0"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TreeViewItem}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition MinWidth="19"
                      Width="Auto"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <ToggleButton x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/>
                        <Border Name="Bd" Grid.Column="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
                            <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                        </Border>
                        <ItemsPresenter x:Name="ItemsHost" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsExpanded" Value="false">
                            <Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/>
                        </Trigger>
                        <!--<Trigger Property="HasItems" Value="false">
                            <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/>
                        </Trigger>-->
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="HasHeader" Value="false"/>
                                <Condition Property="Width" Value="Auto"/>
                            </MultiTrigger.Conditions>
                            <Setter TargetName="PART_Header" Property="MinWidth" Value="75"/>
                        </MultiTrigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="HasHeader" Value="false"/>
                                <Condition Property="Height" Value="Auto"/>
                            </MultiTrigger.Conditions>
                            <Setter TargetName="PART_Header" Property="MinHeight" Value="19"/>
                        </MultiTrigger>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="true"/>
                                <Condition Property="IsSelectionActive" Value="false"/>
                            </MultiTrigger.Conditions>
                            <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                        </MultiTrigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

阅读起来有点清洁。

答案 1 :(得分:1)

++运算符是列表并置运算符。它的类型是[a] -> [a] -> [a]。这意味着它的输入都是列表。正如您从错误中看到的那样,您将x作为++的第一个输入,而x的类型只是a

尝试将此++替换为:,例如:

incList g (x:xs) = g : x : incList (g-1) (xs)

:的类型为a -> [a] -> [a],这应该适用于此处。可能还有其他问题,我没有检查过。